Café Fausse knowledge map

Not the restaurant. MVP = official SRS freeze.

FR / NFR coverage map

In plain English: This companion page maps each official FR-1..FR-18 and NFR-1..NFR-9 ID to where it shows up in the repo and what evidence class we have. The official SRS PDF is the source of truth; docs/srs.md is the working freeze. This page cites those IDs. It does not invent FR-19 or NFR-10. If this map and the freeze disagree, the freeze wins.

This page is not the restaurant. Paths are the in-repo Café Fausse App on main (PRs #9 + timezone #12) plus knowledge/CI where that is the evidence.

flowchart TB
  J["Journey 1–9"]
  pages["J1–J4 pages
FR-1..FR-5 · FR-10..FR-14"] writes["J5–J8 book / newsletter / fail-closed
FR-6..FR-9 · FR-15..FR-18 · NFR-5 NFR-6"] resp["J9 responsive
NFR-8"] J --> pages J --> writes J --> resp

Evidence classes: code = committed file this session; CI = GitHub Actions job in .github/workflows/; local GET / UX (cts-ai, 2026-09-02) = Café Fausse App probe (J1–J8: Vite + Flask + cafe-pg while the DB was up; J9 / NFR-7 Vite slice: Vite-only :5173); owner/sponsor mobile UX this session (2026-09-05) = owner report of Safari on iPhone 16 plus A36 mobile fit on the public hosts; App public-host Chrome/Firefox this session (2026-09-05) = Café Fausse App handoff: Chrome 152.0.7977.83 + Firefox 155.0.1 on cts-ai desktop; five SRS routes PASS on https://cafe.artof.link/; App A36 Brave broadband cold Home (2026-09-06) = Café Fausse App handoff: Samsung A36, Brave (not Chrome), owner-claimed broadband (Wi‑Fi+5G icons visible); method from_recording, png_burst ~200ms, Phone Link on cts-ai; cold Home 466 ms on cafe.artof.link; App A36 Brave broadband reservation submit (2026-09-06) = Café Fausse App handoff: Samsung A36, Brave (not Chrome), owner-claimed broadband; method from_recording, png_burst; reservation submit 233 ms on cafe.artof.link/reservations; App public-host newsletter store (2026-09-12) = Café Fausse App handoff on https://cafe.artof.link/: POST /api/newsletter → 201; email_delivery: skipped / "email not configured"; operator stored customer_id 76, <probe-inbox>; host tip 73d202d (#138); container has no SES_FROM_EMAIL / SES_REGION / PUBLIC_BASE. Store-only. Do not claim outbound send. Inbox receive N/A until env + verified From are wired; Unknown = no probe this session, or a measured number that is not an SRS-budget claim.

Issue #40 recorded J1–J8 (PR #43). Issue #44 records J9 + the Vite-only NFR-7 slice. Issue #117 records the owner/sponsor mobile UX probe this session (2026-09-05). Issue #120 records the App Chrome + Firefox public-host PASS this session (2026-09-05). Issue #123 records the A36 Brave owner-claimed-broadband cold Home stopwatch for NFR-1. Issue #125 records the later A36 Brave owner-claimed-broadband reservation submit for NFR-2. Issue #198 records the App public-host newsletter store probe (2026-09-12) on FR-15 / FR-16 — store-only; do not claim outbound send. This Knowledge VM did not reach cts-ai Vite :5173 / Flask :5000, did not run the phones, and did not open the cts-ai report files. The Journey table below is App’s 2026-09-02 handoff plus the owner report and App public-host browser handoff cited on NFR-7 / NFR-8.

In plain language: the FR/NFR tables are “where the freeze shows up in the repo.” Code and CI are not a stopwatch. NFR-1 is honest met / PASS from the owner-claimed broadband + measured cold Home below. NFR-2 is honest met / PASS from the owner-claimed broadband + measured reservation submit below. That is not a four-browser claim. Friday score-5 talk track: Friday plan.

Journey 1–9 (App naming this run)

Recorded from Café Fausse App (cts-ai) 2026-09-02 Europe/Berlin.

J1–J8 (#40 / PR #43): local UX / GET on Vite + Flask + cafe-pg while the database was up (seeded friday.demo@example.com and newsletter.friday@example.com). After that handoff, App reported cafe-pg unreachable and cts-ai dropped. Those later drops do not erase the J1–J8 PASS numbers from while the DB was up.

J9 + NFR-3 / NFR-8 + NFR-7 Vite slice (#44): later Vite-only local UX on :5173 (2026-09-02). Edge headless screenshots + theme.css (viewports); partial browser matrix. Do not claim Flask + PostgreSQL for that Vite-only probe. That slice is not a public-host GET.

Owner/sponsor mobile UX this session (2026-09-05) (#117): Safari on iPhone 16 — UX validated (restaurant App + Knowledge mobile fit). Sponsor also checks UX on iPhone + A36 (mobile) — source of earlier fit issues. Owner report; this agent did not run those devices. Safari PASS stays mobile Safari, not a desktop Safari probe. A36 browser on the later NFR-1 take is Brave (not Chrome) (#123).

Café Fausse App Chrome + Firefox on the public host this session (2026-09-05) (#120): Chrome 152.0.7977.83 + Firefox 155.0.1 on cts-ai desktop. All five SRS routes PASS on https://cafe.artof.link/ (/, /menu, /gallery, /reservations, /about). Method: Chrome headless dump-dom; Firefox headless screenshots. Reports C:\Users\Public\cafe-nfr7-probe.json / .txt on cts-ai (not in this repo). This Knowledge VM did not open those files. The 2026-09-02 Vite-only Firefox-home note stays prior evidence. NFR-7 stays Partial — not a four-browser claim (desktop Safari not probed; mobile Safari only from #117). NFR-1 met / PASS is the A36 Brave owner-claimed-broadband cold Home (#123), not this desktop dump-dom. NFR-2 met / PASS is the later A36 Brave owner-claimed-broadband reservation submit (#125). ROG Wi‑Fi device stopwatch (#119 / #122) stays a separate evidence note — not the broadband met claim.

Tunnel / Flask (2026-09-02 Vite note): App reported Docker Engine still coming up. Mentioned tunnel https://nine-teams-try.loca.lt/ is ephemeral. Knowledge VM GET of that URL timed out (curl 28, 12s). Do not claim that tunnel is the live share. Public restaurant share this session is https://cafe.artof.link/ (this agent HTTPS GET 200; Lightsail staging #57) — not tunnel-only.

JourneyApp nameResultNotes (this session)Freeze IDs (cite only)
J1OrientPASSHome name, contact, hours, navFR-1..FR-4
J2MenuPASSFour freeze categoriesFR-5
J3OwnersPASSAbout foundersFR-10, FR-11
J4GalleryPASSOfficial images HTTP 200FR-12..FR-14
J5Happy bookPASSTable 27; sample friday.demo@example.comFR-6..FR-9, FR-17, FR-18
J6Full bookPASS30 tables then HTTP 409FR-9, NFR-5
J7NewsletterPASSSample newsletter.friday@example.comFR-15, FR-16
J8DB downPASSHTTP 503 fail-closedNFR-6
J9ResponsivePASSVite-only :5173 (cts-ai, 2026-09-02). Edge headless screenshots under probe-nfr/ (375×812 home, 768×1024 menu, 1280×800 reservations; App reported valid PNG signatures). Viewport meta + @media (max-width: 800px) + Flex/Grid auto-fit in theme.css. Not Flask+Postgres. That Vite slice is not a public-host GET. Public-host mobile UX this session is on the NFR-8 row (owner/sponsor report).NFR-8

Vite routes /, /menu, /about, /gallery, /reservations all returned 200 on that local stack (App this session). That is local UX evidence, not a public-host probe.

Functional requirements

Design column (#227): links each ID to the retroactive Architecture Decision Record(s) that shaped it (ADR index), or says n/a: <reason> when no design decision exists. ADR links point at GitHub because docs/ is not published on this Knowledge site. Each ADR cites official IDs only on its Related requirements: line, and CI checks those IDs against docs/srs.md.

IDSummaryDesignIn-repoEvidenceWhy it matters for the course
FR-1Display Café Fausse’s name prominentlyADR-0005frontend/src/pages/Home.jsx (<h1> from freeze); frontend/src/components/Layout.jsx wordmarkcode; local UX J1 PASS (cts-ai)Home is the first SRS product function. Graders look for the restaurant name on the digital front door.
FR-2Contact + hours (freeze address, phone, Mon–Sat / Sunday hours)ADR-0005, ADR-0006Home.jsx visit/hours cards; Layout.jsx footer; shared/freeze.json; Flask GET /api/sitecode; CI (test_freeze.py); local UX J1 PASS (cts-ai)Freeze data. Changing the address or hours is a spec miss, not a polish.
FR-3High-quality images and a consistent themeADR-0007Home.jsx hero from official images; frontend/src/styles/theme.csscodeCourse image pack is four webps only. Theme must hold across pages (NFR-4 adjacency).
FR-4Nav to Menu, Reservations, About Us, GalleryADR-0001Layout.jsx LINKS; frontend/src/App.jsx routescode; local UX J1 PASS (cts-ai)SRS names those four destinations. Missing a route is a missing FR.
FR-5Menu by category with freeze items and pricesADR-0005frontend/src/pages/Menu.jsx; shared/freeze.json; backend/cafe_fausse/content.py; GET /api/menucode; CI (test_freeze.py); local UX J2 PASS (cts-ai, 4 cats)Prices and copy are SoT. Do not “improve” the menu in MVP.
FR-6Reservation form: time slot, guests, name, email, optional phoneADR-0003, ADR-0006frontend/src/pages/Reservations.jsx; backend/cafe_fausse/validate.pycode; local UX J5 PASS (cts-ai)This is the reservations page the SRS lists as a product function.
FR-7Validate the selected slot is available and validADR-0003, ADR-0006backend/cafe_fausse/slots.py; reservations.py; GET /api/slots; tests in test_reservations.pycode; CI; local UX J5/J6 PASS (cts-ai)Invalid or closed hours must not book. Sunday last seating is freeze hours, not a guess.
FR-8Assign a random table from 30 when the slot has roomADR-0003reservations.py (ORDER BY random()); schema.sql table_number BETWEEN 1 AND 30code; CI (test_reservations.py, test_fail_closed.py); local UX J5 PASS (table 27)Table pool is 30. A 31st table would violate the SRS.
FR-9Success message, or error if the slot is fully bookedADR-0003Reservations.jsx banners; reservations.py fully_booked; test_fail_closed.pycode; CI; local UX J5 PASS + J6 PASS (30 then 409)Fail closed: a full book is an honest no, not a guessed table.
FR-10History: founded 2010 by Chef Antonio Rossi and Maria LopezADR-0005frontend/src/pages/About.jsx (freeze.history)code; CI (test_freeze.py); local UX J3 PASS (cts-ai)About Us copy is freeze text.
FR-11Founder biographies; locally sourced ingredientsADR-0005About.jsx founders + freeze.locallySourcedcode; local UX J3 PASS (cts-ai)SRS About Us is history and founder bios / sourcing, not a slogan page.
FR-12Gallery: interior, dishes, events / behind-the-scenesADR-0007frontend/src/pages/Gallery.jsx; official four webps in assets/images/code; local UX J4 PASS (official images 200)App must not substitute the 17 student-recovered files in supplemental-not-official/.
FR-13Lightbox for enlarged imagesn/a: UI component (Lightbox.jsx); no architecture decision recordedfrontend/src/components/Lightbox.jsx used by Gallery.jsxcode; local UX J4 PASS (cts-ai)SRS asks for enlarged viewing, not thumbnails only.
FR-14Awards 2022/2023 and quoted reviewsADR-0005Gallery.jsx awards + reviews from freezecode; CI (test_freeze.py); local UX J4 PASS (cts-ai)Award names and review quotes are freeze data.
FR-15Newsletter signup with email-format validationADR-0004frontend/src/components/NewsletterForm.jsx; validate.py; test_fail_closed.py invalid emailcode; CI; local UX J7 PASS (cts-ai); App public-host store probe (2026-09-12): POST /api/newsletter → 201 on cafe.artof.link (valid email stored). Store-only. Do not claim outbound send. #198Bad emails must not be stored. HTML type=email plus server check. Public-host 201 is store evidence, not a send claim.
FR-16Store submitted emails in the backend databaseADR-0004backend/cafe_fausse/newsletter.py; customers.newsletter_signup in schema.sqlcode; CI (test_newsletter.py); local UX J7 PASS (newsletter.friday@example.com); App public-host store probe (2026-09-12): POST /api/newsletter → 201; email_delivery: skipped / "email not configured"; operator stored customer_id 76, <probe-inbox>; host tip 73d202d (#138); container has no SES_FROM_EMAIL / SES_REGION / PUBLIC_BASE. Inbox receive N/A. Store-only. Do not claim outbound send. #198Signup is a write. Missing DB → honest no (NFR-6), not a fake success. Public-host store is not outbound send.
FR-17PostgreSQL Customers + Reservations tablesADR-0001backend/schema.sql; backend/cafe_fausse/init_db.py; db.pycode; CI (restaurant-api job); local UX J5/J8 (write while up; 503 when down)SRS names the tables and columns. No database → no booking.
FR-18Flask: insert customer, check availability, random table, confirm or errorADR-0001, ADR-0003backend/cafe_fausse/__init__.py (POST /api/reservations); reservations.pycode; CI; local UX J5/J6 PASS (cts-ai)Back-end reservation system is an SRS product function, not a static form.

Recording helper (not a freeze ID): read-only /operator shows customers + reservations so a recording can see the DB after a booking. Not an admin console (no CRUD / cancel). Not FR-19. Landed on main via PR #58 / issue 54. Prefer https://cafe.artof.link/operator — Knowledge GET 200 (~0.6s). Lightsail staging (#57) — not production forever. Interim backup: https://<STAGING_IP_DASHED>.sslip.io/operator. See the Brief.

Non-functional requirements

IDSummaryDesignIn-repoEvidenceWhy it matters for the course
NFR-1Page load within 3 seconds on standard broadbandn/a: measured outcome (A36 cold Home), not a design decisionIntended SPA + static assets under frontend/ and theme.css.met / PASS — owner-claimed broadband + measured cold Home on https://cafe.artof.link/. Samsung A36; Brave (not Chrome); network: broadband (owner claim), Wi‑Fi+5G icons visible; method from_recording, png_burst ~200ms, Phone Link on cts-ai, 2026-09-06. Cold Home load 466 ms (0.466 s) — blank viewport frame 046242 → full Home+hero 046708; first content ~235 ms at 046477. That is under the SRS ≤3s page-load budget. Report path on cts-ai (cite only; this repo does not invent file contents): %USERPROFILE%\Documents\cafe-artof-evidence\phonelink-a36-stopwatch.json. Tracker #123. ROG Wi‑Fi device stopwatch (#119 / #122) stays a separate evidence note — not this broadband met. Local Vite home 56 ms is still only a local note.The SRS asks for a 3s load on standard broadband. This row records an owner-claimed broadband class plus a measured cold Home of 466 ms.
NFR-2Form submissions processed within 2 secondsn/a: measured outcome (A36 submit), not a design decisionDB_STATEMENT_TIMEOUT_MS=2000 / DB_CONNECT_TIMEOUT in db.py (fail-closed timeout, not a UX stopwatch).met / PASS — owner-claimed broadband + measured reservation submit on https://cafe.artof.link/reservations. Samsung A36; Brave (not Chrome); network: broadband (owner claim); method from_recording, png_burst, 2026-09-06. Submit 233 ms (0.233 s) — start frame 027357 button Booking... → success frame 027590 green Reservation confirmed. Table 27…; pre frame 027124 Reserve a table. That is under the SRS ≤2s form-submit budget. Report path on cts-ai (cite only; this repo does not invent file contents): %USERPROFILE%\Documents\cafe-artof-evidence\phonelink-a36-submit2-stopwatch.json. Tracker #125. NFR-1 stays met / PASS from the prior A36 Brave cold Home 466 ms (#123). The #123 take did not observe a submit. Newsletter on this broadband take was not observed — do not invent that timing. ROG Wi‑Fi reservation 242 ms → confirmed and newsletter 156 ms → subscribed (#119 / #122) remain a separate Wi‑Fi evidence note — not this broadband met. Prior local Vite GET /api/site 32 ms is not a submit stopwatch.The SRS asks for a 2s form-submit budget. This row records an owner-claimed broadband class plus a measured reservation submit of 233 ms.
NFR-3Interface intuitive and easy to navigaten/a: UX quality judged by probes; no design decision recordedLayout.jsx primary nav; App.jsx routes matching SRS pagescode; local UX J1–J8 PASS (cts-ai, DB up) supports navigation. J9 / NFR-3 PASS this session: Edge headless screenshots (home 375×812, menu 768×1024, reservations 1280×800) under probe-nfr/ (App: valid PNG signatures). Vite-only.Course UX is the five SRS pages plus newsletter. J1–J8 is local Journey UX with Flask+DB. Screenshot PASS is Vite-only, not a public device lab.
NFR-4Consistent, visually appealing brandn/a: visual theme in theme.css; no design decision recordedtheme.css (burgundy/cream, Flexbox/Grid); Layout chrome on every pagecodeSRS asks for brand consistency. Aesthetic judgment beyond the committed theme is Unknown.
NFR-5No double or over-bookingsADR-0003Unique index reservations_slot_table; 30-table cap; test_fail_closed.py 31st tablecode; CI; local UX J6 PASS (30 then 409)Integrity is the reservation NFR. A race that assigns table 31 fails the assignment.
NFR-6User-friendly failure handlingADR-0003, ADR-0004test_fail_closed.py (missing DB, unreachable DB, timeout, full slot); frontend error bannerscode; CI; local UX J8 PASS (503 fail-closed)Fail closed: honest no, not a cached yes. Maps to FR-9 when the slot is full.
NFR-7Chrome, Firefox, Safari, Edgen/a: browser compatibility probes; no browser-specific design decisionStandard React SPA + CSS. Partial matrix: Vite-only :5173 (cts-ai, 2026-09-02); owner/sponsor mobile UX this session (2026-09-05); App Chrome + Firefox on https://cafe.artof.link/ this session (2026-09-05); device stopwatch (ROG / Android / Chrome / Wi‑Fi) Chrome-on-Android route smoke (2026-09-05 23:28 CEST).Partial — Chrome PASS (Café Fausse App handoff this session, 2026-09-05): Chrome 152.0.7977.83 on cts-ai desktop; five SRS routes PASS on https://cafe.artof.link/ (/, /menu, /gallery, /reservations, /about); Chrome headless dump-dom. Firefox PASS (same App handoff): Firefox 155.0.1; same five routes; Firefox headless screenshots. Reports C:\Users\Public\cafe-nfr7-probe.json / .txt on cts-ai (not in this repo). Chrome-on-Android PASS 5/5 (ROG): Home/Menu/Gallery/Reservations/About on device stopwatch (ROG / Android / Chrome / Wi‑Fi) (ASUS_I001DC / ROG Phone 2 / Android 10 / Chrome 152.0.7977.75 / Wi‑Fi SSID <wifi-network> −53 dBm / 2026-09-05 23:28 CEST / CDP via adb forward). Safari PASS (owner/sponsor report, #117): Safari on iPhone 16, restaurant App + Knowledge mobile fit. This is mobile Safari, not a desktop Safari probe. Edge PASS all routes with screenshots (Vite-only 2026-09-02). A36 this take: Brave (not Chrome) (#123) — still not a four-browser claim and not a Chrome-on-A36 row. NFR-7 stays Partial. NFR-1 met / PASS is the owner-claimed-broadband cold Home on that take (#123). NFR-2 met / PASS is the later owner-claimed-broadband reservation submit (#125). #44 / #117 / #119 / #120 / #123 / #125.Compatibility is an SRS NFR. Chrome + Firefox public-host PASS plus Chrome-on-Android PASS 5/5 (ROG) plus mobile Safari and Vite Edge is still not Chrome + Firefox + Safari + Edge on desktop.
NFR-8Responsive desktop, tablet, smartphoneADR-0001frontend/index.html viewport meta; theme.css Flex/Grid repeat(auto-fit, minmax(…)) + @media (max-width: 800px)code; J9 / NFR-8 PASS (Vite-only Edge screenshots, 2026-09-02). Public-host mobile note this session (2026-09-05, owner/sponsor report): iPhone 16 Safari + A36 UX fit on cafe.artof.link and Knowledge. Vite-only J9 is not the only evidence. Not an NFR-1 / NFR-2 stopwatch.SRS requires Flexbox or Grid and responsive layout. Vite screenshots are local UX. Public-host mobile is owner/sponsor UX fit — not Flask+Postgres write proof.
NFR-9Modular, documented codeADR-0001backend/cafe_fausse/ packages; page components; README.md; this knowledge mapcodeMaintainability is in the freeze. A single script dump would miss the NFR.

NFR-1 / NFR-2 local Vite notes (not the broadband claim)

App local Vite samples (cts-ai, while the stack was up, 2026-09-02):

These numbers stay a local evidence note. They are not the NFR-1 or NFR-2 met / PASS. Those claims are the A36 Brave owner-claimed-broadband cold Home and reservation submit below.

Device stopwatch (ROG / Android / Chrome / Wi‑Fi) — evidence note only

Café Fausse App handoff via ADB on cts-ai. Not the broadband met claim. This ROG Wi‑Fi stopwatch stays a separate evidence note (#119 / #122). NFR-1 met / PASS is the A36 Brave owner-claimed-broadband cold Home (#123). NFR-2 met / PASS is the A36 Brave owner-claimed-broadband reservation submit (#125). ROG submits stay Wi‑Fi notes, not this broadband met.

ItemValue
DeviceASUS_I001DC (ROG Phone 2), Android 10, ADB
NetworkWi‑Fi SSID <wifi-network> (−53 dBm)
BrowserChrome 152.0.7977.75
Date2026-09-05 23:28 CEST
MethodCDP via adb forward (not manual stopwatch)
Page load (wall loadEvent)Home 846 ms · Menu 370 ms · Reservations 1210 ms
Form submitreservation 242 ms → confirmed; newsletter 156 ms → subscribed
NFR-7 Chrome-on-AndroidHome/Menu/Gallery/Reservations/About PASS 5/5 — Partial evidence. Still not a four-browser claim.

Reports on cts-ai (cite path only; this repo does not invent file contents): %USERPROFILE%\Documents\cafe-artof-evidence\rog-device-stopwatch-issue-119.json (+ .md). Tracker #119.

Device stopwatch (A36 / Brave / owner-claimed broadband) — NFR-1 met / PASS

Café Fausse App handoff. Owner-claimed broadband + measured cold Home on https://cafe.artof.link/. This is the honest NFR-1 met / PASS for the SRS ≤3s page-load budget. Form submit was not observed on this #123 take. NFR-2 met / PASS is take 2 below. Do not invent contents of the cts-ai report file.

ItemValue
DeviceSamsung A36
BrowserBrave (not Chrome)
Networkbroadband (owner claim); Wi‑Fi+5G icons visible
Date2026-09-06
Methodfrom_recording, png_burst ~200ms, Phone Link on cts-ai
Cold Home load466 ms (0.466 s) — blank viewport frame 046242 → full Home+hero 046708; first content ~235 ms at 046477
URLcafe.artof.link
Form submitnot observed on this #123 take — NFR-2 met / PASS is take 2 below

Report path on cts-ai (cite only): %USERPROFILE%\Documents\cafe-artof-evidence\phonelink-a36-stopwatch.json. Tracker #123.

Device stopwatch (A36 / Brave / owner-claimed broadband) — NFR-2 met / PASS

Café Fausse App handoff. Owner-claimed broadband + measured reservation submit on https://cafe.artof.link/reservations. This is the honest NFR-2 met / PASS for the SRS ≤2s form-submit budget. NFR-1 stays met / PASS from the prior cold Home 466 ms. Newsletter on this broadband take was not observed — do not invent that timing. Do not invent contents of the cts-ai report file. ROG Wi‑Fi notes stay separate evidence.

ItemValue
DeviceSamsung A36
BrowserBrave (not Chrome)
Networkbroadband (owner claim)
Date2026-09-06
Formreservation on cafe.artof.link/reservations
Methodfrom_recording, png_burst
Submit233 ms (0.233 s)
Start frame027357 button Booking...
Success frame027590 green Reservation confirmed. Table 27…
Pre frame027124 Reserve a table

Report path on cts-ai (cite only): %USERPROFILE%\Documents\cafe-artof-evidence\phonelink-a36-submit2-stopwatch.json. Tracker #125.

J9 / NFR-3 / NFR-8 viewport notes (Vite-only)

App Edge headless screenshots this session (cts-ai, Vite :5173). Files under probe-nfr/ on that machine. App reported valid PNG signatures. Not committed in this repo. This Knowledge VM did not open those files.

Committed theme (code this session): frontend/index.html <meta name="viewport" content="width=device-width, initial-scale=1.0" />; frontend/src/styles/theme.css @media (max-width: 800px) and grid-template-columns: repeat(auto-fit, minmax(…)).

Public-host mobile UX (owner/sponsor, 2026-09-05)

Owner report this session (#117): Safari on iPhone 16 — UX validated for the restaurant App and Knowledge mobile fit. Sponsor also checks UX on iPhone + A36 (mobile). Hosts: https://cafe.artof.link/ and Knowledge. This agent HTTPS GET 200 on those hosts this session (liveness only — not the device UX). A36 browser on the later NFR-1 / NFR-2 takes is Brave (not Chrome) (#123 / #125). Not a four-browser NFR-7 pass. NFR-1 met / PASS is that broadband cold Home; NFR-2 met / PASS is the later broadband reservation submit.

Public-host Chrome + Firefox (Café Fausse App, 2026-09-05)

Café Fausse App handoff this session (#120): Chrome 152.0.7977.83 + Firefox 155.0.1 on cts-ai desktop. All five SRS routes PASS on https://cafe.artof.link/ (/, /menu, /gallery, /reservations, /about). Method: Chrome headless dump-dom; Firefox headless screenshots. Reports C:\Users\Public\cafe-nfr7-probe.json / .txt on cts-ai (not in this repo). This Knowledge VM did not open those files. This agent HTTPS GET 200 on those five App routes plus /api/health {"ok":true} this session (liveness only — not the browser dump-dom/screenshot probe). NFR-7 stays Partial. Desktop Safari not probed. A36 this take: Brave (not Chrome). NFR-1 met / PASS is the A36 broadband cold Home (#123). NFR-2 met / PASS is the A36 broadband reservation submit (#125). ROG Wi‑Fi device stopwatch (#119 / #122) is separate — not the broadband met.

Prefer live share this session: https://cafe.artof.link/ GET 200. Interim backup https://<STAGING_IP_DASHED>.sslip.io/. Old https://shaky-deer-drive.loca.lt/ is stale. Do not claim production-forever hosting.

Knowledge-site rows (not extra FRs)

These are harness surfaces, not new requirement IDs.

SurfaceIn-repoEvidenceWhy it matters
SRS freeze on this mapknowledge/srs.md, built srs-full.html from docs/srs.mdcode; CI (knowledge-site + srs-present)Graders can see the ID freeze without opening the PDF first.
Honesty vocabularyknowledge/honesty.mdcode; local GET 200 on https://knowledge.cafe.artof.link/honesty.html this sessionPrefer cafe.artof.link as weekend Lightsail staging (#57). Stops claiming production-forever hosting or that the *.artof.link ELB wildcard is Café Fausse.
Teammate briefknowledge/brief.mdcodeMeeting 2026-09-02 19:00 CET; Friday score-5 section.
Friday plan + video/slidesknowledge/friday-plan.md, video-script.md, presentation.md, presentation-sample.mdcodeWorking references for Friday 2026-09-04 and Saturday recording cuts. Not a substitute for the Journey table above.
Journey / NFR recordingthis page; #40 / #44 / #117 / #119 / #120 / #123 / #125App local UX / GET 2026-09-02 (cts-ai); J9 / NFR-3 / NFR-8 Vite slice Vite-only; probe-nfr/ PNGs on cts-ai (not in this repo); owner/sponsor mobile UX this session (2026-09-05) on public hosts; App Chrome 152.0.7977.83 + Firefox 155.0.1 five-route PASS on https://cafe.artof.link/ (dump-dom / screenshots; reports on cts-ai, not in repo); device stopwatch (ROG / Android / Chrome / Wi‑Fi) App handoff 2026-09-05 23:28 CEST; device stopwatch (A36 / Brave / owner-claimed broadband) App handoff 2026-09-06 cold Home 466 ms and reservation submit 233 ms; Knowledge GET of the 2026-09-02 tunnel timed outJ1–J8 PASS while DB was up; J9 / NFR-3 / NFR-8 PASS (Vite-only Edge screenshots + theme.css) plus public-host mobile note (iPhone 16 Safari + A36 UX fit). NFR-7 partial (Chrome + Firefox PASS on cafe.artof.link; Chrome-on-Android PASS 5/5 on ROG; Safari PASS on iPhone 16; Edge all routes on Vite; desktop Safari not probed; A36 this take Brave (not Chrome)). NFR-1 met / PASS (A36 Brave owner-claimed broadband, cold Home 466 ms). NFR-2 met / PASS (A36 Brave owner-claimed broadband, reservation submit 233 ms). ROG Wi‑Fi stays a separate evidence note. Tunnel is not the live share; cafe.artof.link is.
Operator view /operatorApp on main (PR #58 / #54); brief note aboveKnowledge GET https://cafe.artof.link/operator 200 this session (~0.6s). Interim backup https://<STAGING_IP_DASHED>.sslip.io/operator.Read-only recording helper (customers + reservations). Not an admin console. Not FR-19. Lightsail staging (#57); not production forever.
Knowledge nav / readabilityknowledge/style.css; knowledge/build.py nav + section icons; table wrapscode (#69)Map affordance for phone + desktop. Not an NFR-1 / NFR-2 claim. Restaurant NFR-8 is the App Vite record plus the public-host mobile note above.

Out of this table

Florist Path B, 14 hats, Kafka, BFF, 3DX Lab, GitLab, inventing FR-19, outbound newsletter mailer, claiming production-forever hosting. Future #22 / #34–#38 stay parked. Weekend Lightsail #57 does not close #22. Public repo. Do not claim antifragile.