{"ns":"outfitter","title":"Outfitter","version":"1.0","summary":"Outfitter is a practice online storefront: shoppers sign in, browse a six-item catalogue, sort it, open product pages, build a cart and complete a three-step checkout (information, overview, confirmation) with 8% sales tax.","problem":"Shoppers need to find items, trust the prices they see and complete an order without surprises; the order total must always equal item total plus tax.","personas":[{"name":"Shopper","need":"Sign in, sort and browse items, add and remove them, and place an order with a clear price breakdown."},{"name":"Locked-out shopper","need":"Be told clearly that the account cannot sign in."},{"name":"Integrator","need":"Read the catalogue, validate a login and place orders through a small API."}],"goals":["Every account type gets the same correct catalogue, sorting, cart and checkout behaviour; only sign-in speed and lockout differ.","The price a shopper sees is the list price on every page.","Tax is exactly 8% of the item total, rounded to the cent, and the order total reconciles."],"features":[{"id":"SGN","title":"Sign-in","summary":"Login form with per-field errors and account states.","reqs":[{"id":"FR-SGN-01","weight":"Must","text":"A valid account signs in and lands on the Products page showing six products.","accept":["Page title \"Products\" and URL ending /inventory.html","Each of the six cards shows name, description, price and \"Add to cart\""]},{"id":"FR-SGN-02","weight":"Must","text":"Missing fields are reported one at a time, username first, then password.","accept":["Both empty: \"Oh snap: Username is required\"","Username only: \"Oh snap: Password is required\"","The ✕ on the error banner dismisses it"]},{"id":"FR-SGN-03","weight":"Must","text":"Unknown users, wrong passwords and differently-cased usernames are rejected with one generic message and the shopper stays on the login page.","accept":["\"Oh snap: Username and password do not match any user in this service\"","Usernames are case-sensitive"]},{"id":"FR-SGN-04","weight":"Must","text":"A locked-out account with the right password cannot sign in.","accept":["\"Oh snap: Sorry, this user has been locked out.\" and the login page remains"]},{"id":"FR-SGN-05","weight":"Should","text":"The performance-test account signs in only after about 3 seconds; the Login button shows \"Logging in…\" and is disabled meanwhile.","accept":["This delay is accepted, contracted behaviour for that account","After the delay the Products page opens"]}]},{"id":"SES","title":"Session and gating","summary":"Protected pages and logout.","reqs":[{"id":"FR-SES-01","weight":"Should","text":"Protected pages opened without signing in show the login form with an explanation naming the page.","accept":["/cart.html: \"Oh snap: You can only access '/cart.html' when you are logged in.\"","The same for /inventory.html"]},{"id":"FR-SES-02","weight":"Must","text":"Logout returns to the login page, empties the cart and re-gates protected pages.","accept":["After logging out and signing in again there is no cart badge","Opening /inventory.html after logout shows the gating message"]}]},{"id":"CAT","title":"Catalogue and product detail","summary":"Sortable product list and product pages, identical for every account.","reqs":[{"id":"FR-CAT-01","weight":"Must","text":"The catalogue opens sorted Name (A to Z) and can be re-sorted; the list always matches the chosen sort.","accept":["Name (A to Z): Backpack, Bike Light, Bolt T-Shirt, Fleece Jacket, Onesie, Test Everything T-Shirt (Red)","Name (Z to A) is the exact reverse","Price (low to high): $7.99, $9.99, $15.99, $15.99, $29.99, $49.99 — Bolt T-Shirt before the Red T-Shirt (equal prices keep name order)","Price (high to low): $49.99, $29.99, $15.99, $15.99, $9.99, $7.99"]},{"id":"FR-CAT-02","weight":"Must","text":"Every product shows its list price on the Products page, matching the cart and checkout.","accept":["Backpack $29.99, Bike Light $9.99, Bolt T-Shirt $15.99, Fleece Jacket $49.99, Onesie $7.99, Test Everything T-Shirt (Red) $15.99"]},{"id":"FR-CAT-03","weight":"Should","text":"Each product shows its own product image, and every account sees the same product art.","accept":["The six images are distinct from one another"]},{"id":"FR-CAT-04","weight":"Should","text":"Clicking a product name opens its detail page with name, description, price and an Add to cart / Remove toggle that shares the cart with the list.","accept":["The Fleece Jacket opens /inventory-item.html?id=5 showing $49.99","\"← Back to products\" returns to the list","Adding on the detail page shows \"Remove\" there and in the list, and the badge becomes 1"]},{"id":"FR-CAT-05","weight":"Could","text":"An unknown product id shows a not-found page.","accept":["\"ITEM NOT FOUND\" and \"We're sorry, but your call could not be completed as dialled.\""]}]},{"id":"CRT","title":"Cart","summary":"Add, remove, persist and reset items.","reqs":[{"id":"FR-CRT-01","weight":"Must","text":"Every product’s Add to cart button adds that product, flips to \"Remove\", and the cart badge always equals the number of items in the cart.","accept":["Adding all six products gives badge 6","Removing one item lowers the badge by 1","Adding any single product, including the Bolt T-Shirt, shows \"Remove\" and badge 1"]},{"id":"FR-CRT-02","weight":"Should","text":"The cart page lists each item with quantity 1 and its list price and allows removal.","accept":["Title \"Your Cart\"; Backpack $29.99 and Fleece Jacket $49.99 each QTY 1","Continue Shopping returns to Products with the items still in the cart"]},{"id":"FR-CRT-03","weight":"Could","text":"The cart persists across page reloads while signed in.","accept":["After a reload the badge and \"Remove\" buttons are unchanged"]},{"id":"FR-CRT-04","weight":"Could","text":"Menu \"Reset App State\" empties the cart without signing out; About and All Items navigate and the menu closes.","accept":["After reset, reload shows \"Add to cart\" on every product","About shows title \"About\"; All Items shows Products"]}]},{"id":"CHK","title":"Checkout","summary":"Three steps: information, overview, complete.","reqs":[{"id":"FR-CHK-01","weight":"Must","text":"Your Information requires First Name, Last Name and Postal Code, checked in that order, and accepts a typed value in every field.","accept":["\"Error: First Name is required\", then \"Error: Last Name is required\", then \"Error: Postal Code is required\"","Text typed into each field stays in that field only","With all three filled, Continue opens \"Checkout: Overview\""]},{"id":"FR-CHK-02","weight":"Must","text":"The overview shows item total, tax of 8% rounded to the cent, and the total; Finish places the order.","accept":["Backpack: Item total $29.99, Tax $2.40, Total $32.39","Backpack + Bike Light: $39.98, $3.20, $43.18","All six items: $129.94, $10.40, $140.34","The overview shows \"TrailCard #31337\" and \"Free Pony Express Delivery!\""]},{"id":"FR-CHK-03","weight":"Must","text":"Finish completes the order for every account: \"Checkout: Complete!\" with \"Thank you for your order!\", the cart is emptied and Back Home returns to Products with every item showing \"Add to cart\"."},{"id":"FR-CHK-04","weight":"Should","text":"An empty cart can reach the overview (all amounts $0.00) but the order is refused.","accept":["Finish shows the inline error \"Cart is empty\" and stays on the overview"]},{"id":"FR-CHK-05","weight":"Could","text":"Cancel on Your Information returns to the cart; Cancel on the overview returns to Products; the cart is kept in both cases."}]},{"id":"API","title":"API","summary":"Catalogue, login and order endpoints.","reqs":[{"id":"FR-API-01","weight":"Should","text":"The catalogue endpoint returns the six products and a single-product lookup; unknown ids return 404.","accept":["The Backpack has id 4 and price 29.99","404 \"Product not found\""]},{"id":"FR-API-02","weight":"Should","text":"Login maps each outcome to a status and message.","accept":["Empty: 400 \"Oh snap: Username is required\"","Wrong password: 401 \"…do not match any user in this service\"","Locked account: 403 \"Oh snap: Sorry, this user has been locked out.\"","A valid account returns 200"]},{"id":"FR-API-03","weight":"Should","text":"Orders validate shipping fields and compute totals on the server.","accept":["Items [4, 0] for Ada Lovelace 10115: 201 with item 39.98, tax 3.2, total 43.18","Empty last name: 422 \"Error: Last Name is required\"","Only unknown ids: 422 \"Cart is empty\" (unknown ids are dropped)"]}]}],"nfr":[{"id":"NFR-01","weight":"Must","text":"Money is shown with a $ sign and exactly two decimals, and tax is calculated from the item total (8%, rounded half up to the cent) identically in the UI and the API."}],"glossary":[{"term":"Item total","meaning":"Sum of list prices of the items in the cart."},{"term":"Tax","meaning":"8% of the item total, rounded to the cent."}],"outOfScope":["Real payment and shipping","Footer social links"]}