Skip to content

NepWalk MVP — Finished build tasks

History only. Open work is in tasks.md; only the team records assign work.

Review follow-ups — 23 Sep 2026

Owner: Prakash (with AI support). This is the progress source for the 23 Sep code review. Detailed evidence and acceptance criteria are kept outside this repo (ask Prakash). Keep reproduction details out of published docs.

Security gate: SEC-01–SEC-04 must be fixed and regression-tested before real traveller data or external use; review again at the Thu 1 Oct share-link milestone and verify the deployed fixes before launch. These are existing MVP privacy/access guarantees, not optional post-launch polish. Review progress Fri 25 Sep and at the Wed 30 Sep cut-line; log a slip if added work changes the schedule.

  • [x] SEC-01 · High · [be] Safe public/traveller response projections across trips, days and templates. Regression tests with every contact field populated; legitimate owner access and private/cross-organisation protections still pass. Due: security gate. Progress 24 Sep: day and template reads now return public trip fields only — nepwalk-be d701954 (branch feat/stop-places); 25 Sep: trip list, detail and public-slug reads now show outsiders an allowlist of public fields (no contacts, emails, leader's basics, headcount or rooms) — nepwalk-be 08f512e (branch fix/sec-01-trip-reads), 7 tests + 4 mutation checks, 164/164 e2e. Deployed check 25 Sep ✅: anonymous production trip list has no private fields. ✅ Closed 1 Oct: the share link reads through the shareTripView allowlist with switch-off and replace tests — nepwalk-be #26 (d7ef7d7, aac59c8) + #27 (aad91e5, 50ec2f6); templates on one read rule (9853b28, P44). 356/356 e2e, 31 mutation checks. Deployed check 1 Oct ✅ (production, synthetic accounts and trip, leader contacts filled): anonymous read of the share link shows the plan and none of the private fields; unknown token, sub-paths and a changed trip id → 404 / same trip; creator endpoints 401 without login and 404 for another user; the share token is refused as a login (401); off → 404, on → the same link works, replace → old 404. Re-check at the release gate.
  • [x] SEC-02 · High · [be]/[fe] Browser-bound OAuth login transaction. Tests reject missing, mismatched, expired, replayed and wrong-browser callbacks, and prove a valid login. Due: security gate. ✅ 25 Sep — fixed by Sign in with Google (T18): nepwalk-be 7d02ba0 + nepwalk-fe 0ae2083 (branch fix/sec-02-03-google-sign-in). Redirect + callback removed (nothing to force, no tokens in URLs); ID token verified server-side. 14 e2e tests with real signed tokens, 4 + 3 mutation checks, 206/206 e2e, 55/55 Vitest; founder tested locally (Chrome, Brave; new user created, repeat logins reuse it). Deployed check 25 Sep ✅ (production: fake token 401, old routes 404, no tokens in URLs, real Google login works). Re-check at the release gate.
  • [x] SEC-03 · High · [be]/[fe] Credential-safe login handoff and logging. Tests verify no access/refresh tokens in redirect URLs and reject invalid or replayed exchanges. Due: security gate. ✅ 25 Sep — fixed by Sign in with Google (T18): nepwalk-be 7d02ba0 + nepwalk-fe 0ae2083 (branch fix/sec-02-03-google-sign-in). Redirect + callback removed (nothing to force, no tokens in URLs); ID token verified server-side. 14 e2e tests with real signed tokens, 4 + 3 mutation checks, 206/206 e2e, 55/55 Vitest; founder tested locally (Chrome, Brave; new user created, repeat logins reuse it). Deployed check 25 Sep ✅ (production: fake token 401, old routes 404, no tokens in URLs, real Google login works). Re-check at the release gate.
  • [x] SEC-04 · Medium · [be] Runtime-validated request bodies and safe error responses. Bad input returns 400; unexpected failures return a generic 500 without implementation details or private input. Due: security gate. ✅ 25 Sep — nepwalk-be ab94fc7 (branch fix/sec-04-safe-errors): DTOs for trip archive/visibility and template create/rename; KeepRaw/StrictBoolean stop implicit conversion ("false" was saved as true, also on trip create/update isPublic); generic 500 with details in the server log only. 28 tests, 6 mutation checks, 185/185 e2e. Deployed check 25 Sep ✅ (production: bad body → clean 400). Re-check at the release gate.
  • [x] DATA-01 · Medium · [be] Acyclic Place hierarchy and defensive base traversal. Test self-, two-place and longer cycles, reparenting and valid chains; cover seed/import paths. Due: before resolver/base traversal and Thu 24 Sep base-rule integration. ✅ 23 Sep — nepwalk-be PR #9 (feat/place-model) 203c25e (DB trigger: 2/3/6-place cycles, imports, concurrent reparenting) + 72bce8d (findBaseTown stops on a repeated id); protection-removed checks caught.
  • [x] DATA-02 · Medium · [be] Template copies preserve typed itinerary fields and place references, shift dates correctly, and create the trip atomically without copying traveller contacts. Due: Sun 27 Sep Paila/create-trip work. Progress 24 Sep: typed fields and place links copied, one transaction, no contacts — nepwalk-be 9a32d72; date shifting still open (needs the 3-click start date). ✅ 27 Sep — nepwalk-be c30f86b: trips made from a template move every date to their start date; test with a mixed typed template (flight, stay, place, meal, notes, place links) proves every field survives and contacts are not copied.
  • [x] DATA-03 · Low / preventive · [be] Reject blank place names/aliases; normalize matching and handle unknown/ambiguous input explicitly. Allow legitimate duplicate names. Due: resolver/seed work, Wed 23–Thu 24 Sep; before any place-writing API. ✅ 23 Sep — 203c25e (blank names/aliases rejected in the DB) + 72bce8d (resolver: case/space/NFKC matching; found / ambiguous with all candidates / unknown); protection-removed checks caught.
  • [x] QUAL-01 · Engineering · [be] Include e2e files in standard lint; triage existing errors and establish a reviewed clean result or explicit baseline/no-new-errors check. Due: triage Fri 25 Sep; verification plan settled before launch. ✅ 25 Sep — nepwalk-be 79f1683 (branch chore/qual-01-lint-baseline): e2e files linted and type-checked (tsconfig includes test/); npm run lint checks only, lint:fix rewrites; reviewed test-only exception for no-unsafe-* + unbound-method; typed AuthUser; dead cookie guard removed. 0 errors, 0 warnings (was 395 with e2e included); tsc, build, 112 unit + 206 e2e pass. Next: backend CI on PRs so it stays clean.

Close only with evidence: record the fix commit/PR and passing regression checks beside its ID after review. A passing old suite or this tracking entry does not close a finding. Security items also require deployed verification before external real-data use.

Build day 1 — Thu 17 Sep, first half

  • [x] [docs] Write scope.md (authoritative MVP scope)
  • [x] [docs] Write tasks.md (this file)
  • [x] [fe] Expand nepwalk-fe/CLAUDE.md (approved 17 Sep): stack, commands, design-system rules, design brief pointer, known issues
  • [x] [fe] Merge vs rebuild (timebox 1 h): (17 Sep: merged → branch feat/mvp-base, build passes; decision P11) try merging origin/feat/trip_management into the working branch.
  • Done when: merged and building, or a decision is recorded in decisions.md to rebuild the pages on existing components.
  • [x] [fe] Fix auth: ~~store the access token and send Authorization: Bearer~~ ✅ (already on dev) · ~~redirect to /login~~ ✅ · ~~AuthCallback reads data~~ ✅ · remaining: store refreshToken and send { refreshToken } to /auth/refresh, save the new tokens, retry; logout clears both. (17 Sep: done on feat/mvp-base, commit e66befe; founder-tested)
  • Done when: login → trips list loads the user's own trips with no 401.

Extra fixes found during day 2 testing (17 Sep, founder-tested):

  • [x] [be] Update itinerary accepted no category (400) → fixed
  • [x] [fe] Edit/delete/reorder activity and delete day called non-existent routes → fixed to nested routes

Extra fixes found during day 1 testing (17 Sep, founder-tested):

  • [x] [be] Local DB created (decision P12) · CORS allows PUT/PATCH/DELETE (c72a56e) · 3 dead seed photos → Wikimedia (52a1c8d)
  • [x] [fe] CoverImage fallback for missing/broken photos (6ec2d68)

✅ Build day 1 done — 17 Sep.

Build day 2 — Thu 17 Sep, second half

Chunk A done 17 Sep (founder-tested): read access, templates, reorder + itinerary edit fixes — BE 5c5e391, FE da77fab, 23 e2e tests; both repos pushed as feat/mvp-base. Chunk B done 17 Sep (founder-tested): required JWT secrets, refresh-token jti, CORS allowlist — BE 3c6ab4b, 30 e2e tests.

  • [x] [be] Auth guard on GET /trips/:id, /days/:id, /itineraries/:id. Only members (or later a valid share token) can read.
  • [x] [be] GET /trips/public/:slug returns 404 unless isPublic
  • [x] [be] Templates list/get/apply scoped to owner
  • [x] [be] Itinerary reorder rejects IDs that don't belong to the day
  • [x] [be] Fail at startup if JWT_SECRET is missing (no 'default-secret')
  • [x] [be] CORS: restrict origin to the frontend URL from env (currently origin: true reflects any site with credentials). (17 Sep: done; PUT/PATCH/DELETE allowed too.)
  • [x] [be] Refresh tokens: add a unique jti so two tokens issued in the same second differ (today an old refresh token can be reused after rotation); JWT_REFRESH_SECRET required at startup (no 'refresh-secret' fallback)
  • [x] [be] Tests for all of the above.
  • Done when: npm test passes, and tests prove 401/404 for non-members and private trips.

✅ Build day 2 done — 17 Sep.

Build day 4 — Sun 20 Sep

  • [x] [fe] Trip basics form: pax (enrolled / expected max / lock date), leader contact, room mix — on the trip Settings page, with bed-count warnings
  • [x] [fe] Nights strip: whole trip on one line; city blocks from STAY items; empty nights flagged amber
  • [x] [fe] Moves: one tap ✈ flight / 🚐 road on a city change with no move item
  • [x] [fe] Day list showing typed items; add/edit/delete items — item modal now has a type selector with stay / move fields; end-time picker fixed (unset shows --, nothing is sent)
  • [x] [fe] Colour typo fixed: theme.ts error.700 #86291 → #86291f
  • [x] [fe] Automated test suite (extra, 20 Sep): Playwright api (5) + ui (8) journeys covering login, group details, nights strip, one-tap flight and the item modal; own-user-per-test over the API (decision T15)
  • [x] [fe] Bug found by the new suite and fixed: the modal had no max height or scroll, so Save fell off the screen on short viewports
  • [x] [fe] Frontend unit tests: Vitest added (npm test), 44 tests over the trip-basics, nights and item-form rules
  • [x] [fe] Time fields show what is sent: an unset end time shows -- and sends nothing; backend validation messages surfaced (HH:MM, end ≠ start) (found 19 Sep, fixed 20 Sep)
  • Done when: the reference case can be entered by hand in under 10 minutes.

21 Sep 2026: re-planned to requirements.md (P19). Launch ~Wed 7 Oct. The v2 days 5–13 are kept below under Superseded for history.

Build day 5 — Mon 21 Sep

  • [x] [be] R1 night coverage + R2 city continuity as pure functions, reference-case fixture, 16 tests, 5 mutation checks (branch feat/planning-rules, committed 22 Sep as 0600270; unmerged until R1/R2 use bases — build day 8)
  • [x] Product vision written (../../vision.md)
  • [x] MVP requirements v3 (requirements.md); decisions A7, P19–P22, T16
  • [x] Clickable prototype started — hero screens first (day plan, overview, place page)

Build day 7 — Wed 23 Sep

Review dependencies: DATA-01 and DATA-03 above belong with the Place/resolver work; satisfy them before base traversal is used.

  • [x] [be] Place model (P20): type (base town / area / sight / experience / airport / hotel), lat/long, parent, aliases, story, tip, typical duration, photo + credit. Additive migration — 203c25e
  • [x] [be] Resolver: free text → place via name and aliases (AI fallback designed in, not built) — 72bce8d. Same name/alias on two places → asks "which one?", never guesses (founder, 23 Sep)

Build day 8 — Thu 24 Sep

Seed and base-rule work depends on DATA-01 / DATA-03 being verified.

  • [x] [be] Seed ~30 places and experiences (Kathmandu, Pokhara, Chitwan); photos from Wikimedia Commons with credits. Clear, distinct names ("Patan Durbar Square", not "Patan") so the resolver rarely has to ask — ✅ 23 Sep, 116a2e6 (feat/place-seed): 28 places, no experiences (P31); npm run db:seed:places
  • [x] Founder reviews every story and tip (~2 h) — ✅ 23 Sep: 17 drafts reviewed with sources (cave rainy-season closure, crocodile safety, 25-min Bharatpur flight); prototype text kept, "best-preserved" → "well-preserved"
  • [x] [be] R1/R2 compare bases, not typed city; merge feat/planning-rules — ✅ 23 Sep, e7600c2, nepwalk-be PR #11 (Thamel = KTM = Kathmandu; PKR = Pokhara; rules take the place list)

Build day 9b — Fri 25 Sep (done the same day)

Added 25 Sep (slip log): the last security-gate items before the share link.

  • [x] [be]/[fe] SEC-02 + SEC-03 via Sign in with Google (T18): Google button → ID token → POST /auth/google; backend verifies signature, audience, issuer, expiry and verified email, returns tokens in the body; old redirect + callback removed (no tokens in URLs, no callback to force). Tests: fake, expired, wrong-audience and unverified-email tokens rejected; valid token signs in and creates or links the user (S16, S17, S22) — ✅ 25 Sep, be 7d02ba0, fe 0ae2083. Works in Chrome and Brave; Firefox: button does nothing (backlog).
  • [x] Founder: Google Cloud Console → OAuth client → Authorized JavaScript origins https://nepwalk-fe.vercel.app and http://localhost:3000 — ✅ 25 Sep: new client in the NepWalk project (Testing mode is enough: basic scopes are exempt from the test-user list). At merge: Vercel NEXT_PUBLIC_GOOGLE_CLIENT_ID before merging; Render GOOGLE_CLIENT_ID = new ID after, then delete GOOGLE_CLIENT_SECRET + GOOGLE_CALLBACK_URL and the old redirect URI.
  • [x] QUAL-01 triage (Fri 25): e2e files in lint, error count recorded, baseline plan — ✅ went further: full lint clean (be 79f1683)

Build day 10 — Sun 27 Sep (back on its original day, 25 Sep)

Include DATA-02 in the Paila/create-trip work; verify a mixed typed itinerary survives copying and date shifting.

  • [x] [be] Three Pailas as templates (P22): Kathmandu 3 days · Kathmandu + Pokhara 7 days · Kathmandu + Pokhara + Chitwan 10 days — ✅ 27 Sep, nepwalk-be ded2df9 (feat/pailas): public templates owned by a NepWalk user that cannot sign in; every stop linked to a place; checked against R1/R2; day 1 = 2000-01-01 until the 3-click trip shifts dates; npm run db:seed:pailas. 9 data tests + 6 e2e, 6 mutation checks, 212/212 e2e. Founder to review the content (titles, times, order)
  • [x] [be] 3-click trip (P24): parse "N days in " (days + town aliases, no AI) → matching Pailas ranked by popularity and preferences → create with days, people, preferences and included services; every date shifts to the start date; reuses the templates module — ✅ 27 Sep, nepwalk-be c30f86b (feat/three-click-trip, on top of feat/pailas): GET /templates/match?q= (days / nights / weeks + towns by name or alias; unplaced text returned as unknown, never guessed) lists templates that visit every town and can be fitted to the length; POST /templates/:id/trips fits the length (trims sightseeing days from the longest stay, or adds free days in the last town; R1/R2 hold for every length up to 14 days), moves every date to the start date, stores people + preferences, renames "in 7 days" titles. 18 mutation checks, 152 unit + 236 e2e. Not yet: included services (next item, slots); ranking by popularity and preferences (no usage data; Pailas get interest tags after O21)
  • [x] [be] Automatic slots and sizes: hotel nights + rooms from people, vehicle class from people + luggage (R5), flight seats; skipped services leave no slot — ✅ 27 Sep, nepwalk-be 7f6e6ca (feat/build-day-10): ServiceSlot table (additive migration) + trip bags and includedServices; hotel per stay (nights, rooms twin-share, odd one single), flight per flight, guide per sightseeing day, one vehicle per road stretch (P35); meals and activities get no slot (P34); class from people + bags (limits under review, O22). 11 mutation checks, 173 unit + 246 e2e. Not yet: re-sizing when people or bags change (R10)
  • [x] [be]/[fe] Minimal vendor list (P27): admin adds vendors (type, area, capacity, verification); each service slot shows its vendor with "Choose" — the first fitting one is the NepWalk pick — ✅ 27 Sep, nepwalk-be 1fe6129 + nepwalk-fe d5b74a8 (feat/build-day-10): Vendor table (additive migration; the database refuses a verified vendor without proof); admin-only add / edit / verify with proof (who + when) / block (removed from every slot); each slot lists verified vendors of the same service and town with enough rooms or seats, smallest first = NepWalk pick; only a fitting verified vendor can be chosen. Frontend: /vendors and /trips/[id]/services, admin links. 15 mutation checks, 179 unit + 274 e2e (be), 65 Vitest + build (fe). Playwright not written: tests can't make an admin over the API yet

Build day 11 — Mon 28 Sep

  • [x] [fe] Day plan, Visitacity pattern (M1): day tabs, photo cards (time, duration, story, tip), tonight's stay inline (P17), travel connectors — time from lat/long plus a small table for long hops (KTM–PKR) — ✅ 28 Sep, nepwalk-fe #19 (night shift 27 Sep: src/lib/travel-time.ts, day tabs + photo cards, tonight's stay inline, travel connectors)

M1 revision (feature card features/M1-day-plan.md, A13 — from the 27 Sep prototype review):

  • [x] [fe] Web / tablet day list "Day N · title · date" + "Night: ", top tabs mobile only; pagination footer → edge arrows (web) / swipe (mobile) — ✅ 28 Sep, nepwalk-fe #19
  • [x] [fe] Web row cards (photo left), full main width until M13; transport items as travel lines — ✅ 28 Sep, nepwalk-fe #19
  • [x] [fe] Floating "+" → drawer (web) / bottom sheet (mobile) replaces the "Add new activity" bar — ✅ 28 Sep, nepwalk-fe #19
  • [x] [fe] Link a stop to a library place from the edit form (photo, credit, story, tip) — ✅ 28 Sep, nepwalk-fe #19 + nepwalk-be #20 (GET /places?q=)
  • [x] [fe] Leader / traveller view hides edit controls and helper warnings; empty-day, loading, error states — ✅ 28 Sep, nepwalk-fe #19 (editor = trip creator, P36)
  • [x] [fe] Notes label → "Notes for travellers — everyone on this trip sees them" (28 Sep) — ✅ 28 Sep, nepwalk-fe 517caaf (feat/build-day-11b)
  • [x] [fe] "+ Add hotel" opens the add form with type "Stay" preset (defaultType) (28 Sep) — ✅ 28 Sep, nepwalk-fe 0c9bbcd
  • [x] [fe] Rewrite stale Playwright specs for the new day plan: tests/ui/nights-strip.spec.ts (strip removed, P17 → tonight's stay + day-move connector) and tests/ui/itinerary-item.spec.ts ("Add New Activity" → floating "+", data-testid="add-stop"); run just these two by hand next day (28 Sep) — ✅ 28 Sep, nepwalk-fe c7e955e: itinerary-item + new tonight-and-moves (replaces nights-strip), 7/7 passed
  • [x] Discuss (next M1 session): tonight's stay at the top of the day vs last; the floating "+" button — ✅ 28 Sep: top line (nepwalk-fe c22990d); "+ Add stop" in the web header, floating "+" on phones (d1504ac)

Build day 12 — Tue 29 Sep

  • [x] [be]/[fe] Place page (M3) — spec: features/M3-place-page.md (agreed 28 Sep; 3 tasks, access tiers P37) — ✅ 29 Sep, founder-tested. nepwalk-be 8488ab8: GET /places/:slug in three tiers (public teaser · trip insider · admin), 404 / 400, 30 requests a minute per visitor; 11 e2e tests, 10 mutation checks. nepwalk-fe d0163bf + 70aa017 + 2cb6b80 + a56fcda (feat/build-day-12): /places/[slug] page with all states; linked stops on the day plan open it and "Back to Day N" returns to that day (?day=); founder review: header on the place page (landing header when signed out), "Oops!" not-found with a link to the main page, signed-in users skip the sign-in pages (except the password-reset link). 16 + 7 + 9 Vitest tests, 19 mutation checks; Playwright spec written, not run. Merged 29 Sep (be #22, fe #21); TRUST_PROXY_HOPS=2 set on Render — rate limit still loose, see build day 18
  • [x] Open (founder, 29 Sep): should the trip page use the app header too ("header on every page")? Today it keeps its own top bar (M1) — ✅ yes, done 29 Sep (e624363)
  • [x] [be]/[fe] Culture (M2): word of the day, festivals on the trip dates, experiences as stops — card agreed 29 Sep: features/M2-culture.md — ✅ 29 Sep (built the same evening), founder-tested. nepwalk-be 6f546dc (words + festivals data, wordsForTrip / festivalsForTrip; 18 unit tests, 15 mutation checks) + dd07134 (GET /trips/:id/culture, same read rule as the trip; 8 e2e, 10 mutation checks); nepwalk-fe 8e2f271…76532d5 (word line in the prototype's style above tonight's hotel, "Learn more >" drawer with the words so far, crimson festival line and "On your dates" cards, goodbye on the last day; tokens saffron / crimson). Playwright spec written, not run
  • [x] [fe] Trip page layout from founder review (29 Sep): app header on trip pages; trip title + Private chip head the day list; "← Back" beside the day; green icon actions by "Add stop"; day list "Day 1: title - Wed, 30 Sep"; no "Active Plan" — nepwalk-fe e624363, 8a5b4f7, f953724
  • [x] Design talk (founder, Wed 30 Sep): app header and trip page look, against the SVG designs in NepWalk/docs/design-reference/nepwalk-svg-designs/ (landing, signed-in home, trip overview, daily itinerary; outside the repos). Card first (A13), then build — ✅ 30 Sep: day plan picks from the UX review (M1 Revision 2); header nav "My trips · Pailas", no Explore; design 03 becomes the share link's public preview (M5 card, later the members' Overview tab, M4); design 02 is the target for Sunday's trips list

Build day 13 — Wed 30 Sep

  • [x] Review all eight follow-ups above at the cut-line; preserve the security gate and log any schedule impact. — ✅ 30 Sep: 7 of 8 closed with evidence, and every fix commit is on nepwalk-be / nepwalk-fe main. SEC-01 is still open (the share link must reuse publicTripView, with revocation tests) and stays on build day 14; the security gate holds. QUAL-01's verification plan is not yet settled: there is no backend CI on PRs, so the lint baseline is kept by hand until then. Decide by the release gate. SEC-02/03/04 get their deployed re-check at the release gate. No schedule impact, no slip.
  • [x] [fe] Maps (P25): whole-trip map on the overview + a map per day (numbered stops, tonight's hotel, "Open in Google Maps"), OpenStreetMap tiles — spec: features/M13-maps.md (agreed 28 Sep; 5 tasks there) — ✅ 30 Sep, nepwalk-fe feat/build-day-13: 376a4c7 + f183bc0 (day map: numbered pins matching the cards, 🏨 last, route line; sticky right column from 1024 px, full-screen "Map" button below; pin tap scrolls to and highlights the card), b8c48f1 (minimal MapLibre + OpenFreeMap map, T19), d1ccd09 ("Open day in Google Maps", first 9 stops + hotel; per-stop link), 6d6e530 (whole-trip map from "Trip map" in the sidebar: one pin per overnight town with nights, flights dashed; town position from the library's base town, never guessed), b933f89 (states: empty day message, loading, tiles unavailable). 30 new Vitest tests, 19 mutation checks; security S13, S14, S15. Playwright spec tests/ui/day-map.spec.ts (5 journeys) written, not run. Not on phones: the trip map link lives in the sidebar (web/tablet only)
  • [x] Formal plan revisit + cut-line. If behind, cut in this order: overview map (→ list) · festivals and word of the day · install prompt (keep the manifest). Never cut: day plan, place data, share link, access tests, backups — ✅ 30 Sep (founder): no cut, launch stays Wed 7 Oct; maps done by midday. Keep-warm ping and backup script → after the MVP with no-code stand-ins (A14). Church trip built Mon 5 with defaults; leader reminded Mon 5 or Wed 7. Vendor research brief → after the MVP (team not ready). Afternoon: design talk + share link card (M5)

  • [x] [fe]/[be] Day plan polish from the UX review (founder, 30 Sep) — M1 card, Revision 2 — ✅ 30 Sep, nepwalk-fe feat/build-day-13b: 0287fe8 ("1 day", My trips), fe4c0c4 (Directions, Nepal time), 93a2bc0 (hotel → stops → hotel flow), 9e0098d (meal not included), d6e543c (Tomorrow card + firm scroll), ecb260f (phone header, ⋯ menu); nepwalk-be 453073e (place stories free of trip timing; re-run npm run db:seed:places after merge). Each rule test-first with mutation checks. Not seen in a browser yet: the local dev server was down

Build day 14 — Thu 1 Oct

  • [x] Security checkpoint: SEC-01–SEC-04 fixed and regression-tested before real-data/external sharing; apply the same privacy boundary to the new share routes. — ✅ 1 Oct: SEC-01 closed with a deployed check (see Review follow-ups); SEC-02/03/04 closed 25 Sep. All four get a re-check at the release gate
  • [x] [be] Share link (M5): revocable token, view-only, no private data — responses go through publicTripView (SEC-01) — ✅ 1 Oct, nepwalk-be #26 (d7ef7d7, aac59c8): ShareLink table, creator-only get / create / replace, GET /share/:token through the shareTripView allowlist, one 404 for unknown and replaced links, 30 requests a minute, token masked in logs. 14 e2e + 7 unit tests, 25 mutation checks; founder-tested locally
  • One link, one step (P45, 1 Oct): Share makes the link on first use; no Publish, no public preview page. Card: features/M5-share.md
  • [x] [fe] Share sheet (M5 task 3, P45): outlined Share button → the link, Copy, Share… on phones; heading chip "Private" / "Shared by link" — ✅ 1 Oct, nepwalk-fe ea0e4b2 (feat/build-day-14); 9 Vitest tests, 12 mutation checks
  • [x] [fe] Shared trip page /s/[token] (M5 task 4): view-only day plan, ?day=N, credit footer, "no longer active" state — ✅ 1 Oct, nepwalk-fe 43af527. Not in the shared page yet: word of the day and festivals (their endpoint needs a signed-in member), the whole-trip map (needs the place library), tapping a stop through to its place page
  • [x] [be]/[fe] Share popup with one switch (P45): on = anyone with the link can view, off = private; the same link comes back when switched on again — ✅ 1 Oct, nepwalk-be aad91e5 + 50ec2f6 (DELETE /trips/:id/share-link; 8 e2e, 6 mutation checks, 356/356 e2e), nepwalk-fe de38525, ed47198. Also: "Print day" removed, "Save as my Paila" is an icon by Share, header row aligned (7fab0bc, fb86910, 3cc4432)
  • [x] [fe] Copy day as text (P42): the leader's Messenger format, ending "Full plan and map: · made with NepWalk" — ✅ 1 Oct (back on its day, see slip log), nepwalk-fe b94b2d3 (feat/build-day-14c): "Copy day" in the day header on the trip page and the shared page; heading with date, day and town, tonight's hotel, times as H:MM, travel as "Leave for …", meals "(pay locally)" except breakfast, assumed to come with the hotel (founder, 1 Oct; to revisit), the link opened on that day (only once the trip is shared). nepwalk-fe 7f7666d applies the breakfast rule to the stop card too. 19 Vitest tests, 12 mutation checks
  • [x] [be] Access tests: no token = no trip; revoked token fails; changed IDs fail; no leader contact or emails in the share view — ✅ 1 Oct, nepwalk-be #26 (test/share-read.e2e-spec.ts, test/share-link.e2e-spec.ts)
  • [x] [be] Templates use the one read rule (S1) (found 27 Sep): TemplatesService.findById, match and findAll check "owner or public" themselves instead of canViewTrip. Safe today (same result), but a second access check can drift. Move them to canViewTrip with anonymous / outsider / owner tests (~45 min) — ✅ 1 Oct, nepwalk-be 9853b28 (feat/build-day-14), decided differently (P44): the note above was wrong, canViewTrip also admits trip members and organisation members. Templates keep owner-or-public; the rule now lives in one helper (template-access.ts) used by list, detail, match, apply and create-trip. 6 unit + 19 e2e tests (anonymous, stranger, trip member, organisation member, creator), 8 mutation checks, 218 unit + 348 e2e

Build day 16 — Sun 4 Oct

Merged Mon 5 Oct: nepwalk-be #29, nepwalk-fe #30, nepwalk-docs #45. Decision P48 came out of the review.

  • [x] [fe] Trip setup drawer, creator only (P18), with the leader's basics — ✅ 4 Oct, nepwalk-fe 9a2ed48 + 847a071: trip page → ⋯ → "Trip setup": start date, people, rooms, flights in and out (Nepal time), interests, pace, budget level, the leader's contact; saving keeps the drawer open; warnings for beds short and for landing after the trip starts; the "Group & rooms" card left the trip's Settings page. 21 Vitest tests, 7 mutation checks. nepwalk-be 06f8c49: an empty leader email clears it (it returned 400, so the form could not be saved without one). A start date, a flight time, a pace or a budget level can be changed but not cleared yet
  • [x] [fe] Trips list (many trips, many leaders) · 3-click new-trip flow (P24) · stop editor: add from the library, edit, remove with undo (P26); helper warnings inline (M11) — ✅ 4–5 Oct. Trips list (design 02), nepwalk-fe 26d0177 + 07197d2: "Up next" card with dates, the first day and one button; a trip that is on today reads "Happening now" and opens on today's day; Upcoming / Past tabs; "Plan a new trip" tile; the Invitations tab shows only while an invitation waits (P40); no search. 29 Vitest tests, 10 mutation checks. 3-click flow: already built (build day 10 and M7); "Start from scratch" moved above the Pailas (founder, 5 Oct). Stop editor: add from the library, edit and both warnings (no hotel tonight, a move with no travel) were already built; remove with undo is new — nepwalk-fe e2f8bc8 + 847a071: the stop is hidden at once and deleted after 6 seconds, so an undo keeps the stop and the services chosen for it. 16 Vitest tests, 7 mutation checks. Playwright specs written or updated (trip-basics, dashboard, stop-remove-undo), not run
  • [x] [be] Service slots for every trip (found 27 Sep) — ✅ 4 Oct (night run + founder review), nepwalk-be ce8d24c + 2417c9c + 5ea57c0 + 26f780e: the slots are planned again in the same transaction as every change to stops, days, start date or people; a vendor stays while it still fits; a confirmation stays only when nothing it was made for changed; a moved start date clears every confirmation (P48) and moves the end date with it; POST /trips saves all four services when none are given. 423 e2e tests; every rule and call site mutation-checked. Bags and included services cannot be changed after the trip is made — October backlog (P48)
  • [x] [fe] PWA (T16): manifest, icons, install prompt (from Fri 2 Oct) — ✅ 4–5 Oct, nepwalk-fe e4d3bee + 07197d2: app/manifest.ts, icons 192 / 512 / maskable / Apple touch, theme colour; an install offer on the trips list and an "Install NepWalk" section on Settings (button, or the steps on an iPhone and in other browsers); the browser's install prompt is caught at the app root. No service worker: offline comes later. The icon is a placeholder (white route mark on green). 13 Vitest tests, 7 mutation checks
  • [x] [be] Slot order on a travel day — ✅ 4 Oct (night run), nepwalk-be e92f71a: one comparator, by date, then flight · vehicle · hotel · guide, used by the planner and every slot read

Build day 20 — Wed 14 Oct (adding a stop in two taps)

Card: M1 revision 3 (founder, 14 Oct). Comes before the mission-trip Paila.

  • [x] [fe] Kind chips instead of the dropdown; times suggested from the stop above + the place's typical duration; one-line time with "Change"; "Save & add another" starts where the last stop ended — ✅ 14 Oct, nepwalk-fe feat/build-day-20; founder tested. Every kind times itself: a meal by which meal (breakfast 45 min · lunch 60 · dinner 90 · snack 30), a move by the towns it joins, a hotel as one check-in line; an end set by hand is never replaced
  • [x] [fe] "+" between stops in edit mode, opening the sheet for that slot — ✅ 14 Oct: above the first stop, between stops and below the last, on the day's line; a tooltip on hover
  • [x] [be]/[fe] Shift the rest of the day when a stop's time changes or a stop is added in the middle (one backend call, one transaction) — ✅ nepwalk-be PR #37, nepwalk-fe PR #37

Added by the founder on the day (14 Oct), done in nepwalk-fe feat/build-day-20:

  • [x] [fe] Food: which meal is asked apart from the kind (smaller chips), picked by the time (before 10:30 breakfast, before 15:00 lunch, else dinner); "Where?" is a field that takes a library place or keeps the typed text
  • [x] [fe] Hotel: one "Which hotel?" field (a NepWalk hotel from the list, or a typed name that shows as not confirmed); the town comes from that night; nights as chips 1–4 set the check-out, dates one tap away
  • [x] [fe] Travel: "From" fills itself from where the stop above ends (or last night's hotel) and shows as one line; "To" takes a library place or typed text
  • [x] [fe] Tapping the start / end hotel row opens the hotel's card in the side sheet; the "Tonight" toggle is gone
  • [x] [fe] Header: Copy day, Share and Edit / Done are icons with a tooltip (on hover only, gone on click, gone by itself after a few seconds); no "Add stop" button (the "+" adds stops); the ⋯ menu only holds "Make private"
  • [x] [fe] Day list (web), edit mode: rename and delete on each day's row (always on the selected day, on hover elsewhere); tapping the selected day's name edits it. Phones keep both in the header
  • [x] [fe] Trip settings page: tabs "General" (save as my Paila, visibility, archive, delete trip) and "Trip setup" (moved from the drawer)
  • [x] [fe] "To confirm" chip with the count as a badge

Night part, finished on the day (15 Oct), nepwalk-be feat/build-day-20:

  • [x] [be] Restaurants are a kind of place: 10 in Thamel, Lakeside and Sauraha, pins from OpenStreetMap; GET /places?types=RESTAURANT returns only restaurants. A chain's branches (OR2K, Roadhouse Cafe) share a name and the day's town picks the branch — ✅ 15 Oct
  • [x] [be] Hotels come from NepWalk's verified hotel vendors: GET /vendors/hotels?q=&town= for any signed-in user (id, name, town only); a stay links to its hotel (vendorId), never shown to outsiders or on the shared link. Sample hotels for local testing: npm run db:seed:sample-hotels — ✅ 15 Oct
  • [x] [be] npm run db:migrate:test applies migrations to the _test database only, so night runs can run the e2e gate after a migration — ✅ 15 Oct
  • [x] [fe] The stop sheet searches each kind's own things: Food → restaurants and areas in the day's town, Hotel → verified hotels in that night's town (a typed name stays "not confirmed"), Travel "To" → towns, areas and airports — ✅ 15 Oct, nepwalk-fe feat/build-day-20; picking a hotel saves its vendorId, editing the stay shows it picked