{"ns":"flow","title":"Flow benchmark fixture","version":"1.0","summary":"Flow benchmark is a one-page fixture: a heading, a status line and a single Name field with a Save button. Saving shows the saved name in the status line; a small API mirrors the page.","problem":"Testers and automation runners need a minimal, fully predictable page against which every message and rule can be checked exactly.","personas":[{"name":"Tester","need":"Verify page text, validation and keyboard behaviour against exact wording."},{"name":"Automation runner","need":"Read the page faithfully and report disagreement between an expectation and what is shown."}],"goals":["The page shows exactly the wording specified here.","Validation rules are identical on the page and in the API."],"features":[{"id":"PAG","title":"Page content","summary":"Heading, status line and form shown on load.","reqs":[{"id":"FR-PAG-01","weight":"Must","text":"The page at /flow/ shows the heading \"Flow benchmark\", a status line reading \"Ready\" and a form with one text field labelled \"Name\" and a \"Save\" button.","accept":["The status line always starts as \"Ready\"; it never reads \"Offline\" or any other wording on load","The Name field is empty on load"]},{"id":"FR-PAG-02","weight":"Should","text":"The status is not persisted: reloading the page resets it to \"Ready\" and empties the Name field."}]},{"id":"SAV","title":"Save and validation","summary":"Saving a name and rejecting empty input.","reqs":[{"id":"FR-SAV-01","weight":"Must","text":"Saving a name replaces the status with \"Saved: <name>\".","accept":["\"Ada\" shows \"Saved: Ada\"; the wording is \"Saved\", not \"Stored\""]},{"id":"FR-SAV-02","weight":"Must","text":"An empty name is rejected with \"Name is required\" in the status line, before any request is made."},{"id":"FR-SAV-03","weight":"Should","text":"The name is trimmed before validation and saving.","accept":["Only spaces: \"Name is required\"","\"  Grace  \" is saved as \"Saved: Grace\""]},{"id":"FR-SAV-04","weight":"Should","text":"Each successful save replaces the previous one; only the latest name is shown.","accept":["Saving \"Ada\" then \"Alan\" shows \"Saved: Alan\""]},{"id":"FR-SAV-05","weight":"Should","text":"Pressing Enter in the Name field submits the form exactly like the Save button."}]},{"id":"API","title":"Status and save API","summary":"HTTP endpoints that mirror the page.","reqs":[{"id":"FR-API-01","weight":"Should","text":"POST /api/flow/save with a name returns 200 {\"status\":\"Saved: <name>\"}; GET /api/flow/status then returns status \"Ready\" and lastSaved set to the name."},{"id":"FR-API-02","weight":"Should","text":"POST /api/flow/save with an empty or missing name returns 422 with errors.name \"Name is required\"."}]}],"nfr":[{"id":"NFR-01","weight":"Should","text":"The status line is a polite live region (role \"status\", aria-live \"polite\") and the Name field is associated with its label."}],"outOfScope":["Persistence across browsers","Styling"]}