# Feedback browser checkpoint — v0.17

28 October 2026. This bounded local journey is verified using fictional records. It does not approve live SHS, a hosted service or the whole white-label product.

The owner and customer used the actual interface on `http://localhost:8789`. Two customers with identical invented name, email, phone and address were saved as distinct records. Their two completed jobs remained separate. Three feedback requests and three immutable private responses were created through the interface; none were seeded through an API. Harbour Homeworks remained empty. No portal account or new password was needed.

## What was checked

| Branch | Browser actions and saved result |
| --- | --- |
| A: private first | Select the exact completed shelf job; prepare a protected local capture. Enter all four ratings, choose No for recommendation, and submit private marker text with public permission off. The owner sees the original answers; public pages show nothing. Missing ratings produce an error and retain the draft. |
| A: deliberate publication | Replace the private publication choice with a distinct fictional public name and statement; explicitly include the overall rating. Customer preview and confirmation save permission without publishing. Owner preview and a second confirmation publish only those approved fields on the loopback site. |
| A: withdrawal | The customer withdraws. Fresh selected-page and home-page views omit the statement. A stale owner preview is rejected. Reload/reopen retains private answers and approval/withdrawal history, with no current publishable projection. |
| B: separate identity | The matching-contact customer has a different code and sees no A response. B selects different public text and keeps the rating private. Owner notes, high priority and tags preserve publication. |
| B: material correction | Changing B's fictional email hides the testimonial and revokes its code. Restoring the original email does not revive consent or access. A stays independently withdrawn. B's original answers and suspended approval remain recorded. |
| B2: repair and renewed access | A reasoned replacement request preserves the old response/history. New private answers are saved. A valid access check preserves an unsaved public-choice draft; a stale save rejects it without losing text. Owner revocation clears the already-open private page automatically. Reissue gives fresh feedback-only access to the saved answers; a new customer choice and deliberate owner publication produce the final statement. |

The final source dataset contains A withdrawn, original B suspended/revoked, and replacement B2 deliberately published without a public rating. All 16 original request/consent/publication events remain. The 4.33 private average includes all three responses; it is never presented as a public aggregate.

## Two repairs

1. **Revoked feedback could remain on an open page.** A contact change revoked the code at the server, but a failed subsequent action still left private answers visible. Feedback-only access now revalidates separately from a portal session, following same-origin changes, focus/visibility and a 30-second visible-page check. Failed or unavailable validation clears the view and code; a 10-second deadline bounds a hanging check. Valid checks leave draft choices alone. Generation checks prevent late operations from restoring cleared access. The repaired browser test automatically cleared both saved private text and an unsaved choice after revocation.
2. **The owner list could show an old publication state.** Back to feedback now fetches current list/counts. The retest immediately showed the saved response/permission states, and a full reload retained them.

Seven new client regression cases cover feedback-only validation, safe change notices, valid drafts, revoked/unavailable access, overlapping requests, deadlines and late results. The existing portal clearing behavior remains tested.

## Repeating the short walkthrough

Use a fresh fictional dataset with the launch command in README; do not point this code at the preserved owner review. Keep invented contact addresses under `.example`.

1. Create an enquiry, complete its job, then open Feedback. Select the exact job/customer IDs and prepare the local capture. No message is sent.
2. Open the capture and copy its code only into the same local business's feedback form. Hide the capture afterward. Do not put a code in a URL, screenshot or shared document.
3. Submit private answers first. Leave the optional public box off. Reopen the owner request and the selected-testimonial page to compare private and public results.
4. If testing publication, enter a separate public name and statement, choose the rating option deliberately, review and confirm. Then use the owner's exact preview and Publish testimonial locally.
5. Withdraw through the customer control. Reload public pages and reopen owner history. An old preview cannot grant permission again.

The code page intentionally displays the business and request state, but omits job titles, customer contact details and internal job/customer IDs. Exact binding was verified in owner UI and separately against saved/API records; customer-side job-title display was not demonstrated. A code is a bearer credential, not proof of email ownership or delivery.

## Evidence and limits

[Milestone checks](feedback-journey-milestone-checks.json) distinguish actual browser actions, automated tests and recovery. [Browser evidence](../../SHS-Feedback-Verification-v0.17/verification.json) contains nine screenshots, saved DOM observations, keyboard dimensions and record/recovery audits. Credential values are excluded. A 689 × 751 panel showed visible keyboard focus, the explicit confirmation checkbox and no horizontal document overflow. This is not a phone, touch or screen-reader assessment.

The public selected page and home strip were checked after fresh retrieval/reload. Existing downloaded/open copies are not recalled; home-focus timing and cross-device/background timing were not independently established. Expiry, concurrency, replay, foreign IDs, portal/document denial and website-history non-revival have separate automated/API evidence. No customer sign-in was invented.

An unused customer-transfer form was left without saving. Overlapping leave-dialog markup observed when automation addressed background controls is retained in the wider modal/focus queue; it is not a completed transfer or accessibility check.

**611 backend tests, 101 client tests, 79 structural render checks and the build passed.** The full backend run has versioned JUnit XML at `test-results-v0.17.xml` and a separate console log. The old generic XML is historical evidence. No backend schema or dependency changed: 207 method/path policies, format 11 and pinned formats 1–10 remain.

## Recovery and preserved state

The QA server was stopped and the actual UI dataset was backed up and restored into a fresh folder on this Mac. Every original private response and history prefix matched. All four old feedback codes, old test sessions and old passwords failed. Restored requests were revoked, previously approved permission suspended, and all three historical publications hidden. Public count stayed zero, including after access-only reissues; renewed access alone could not publish an old or withdrawn statement. A second-generation backup verified. These are CLI/test-API checks, not restored-browser or second-machine proof. The original fictional source remains retained.

The original ZIP, both 275-file source references, all 18 prior code archives, normal data and frozen v0.12.1 owner-review runtime/data/session remain unchanged. Only QA tabs 26–29 and the extra server on 8789 were closed. The owner review remains on 8788 and does not show v0.17.

All 45 capabilities remain tracked and all 14 original SHS findings remain OPEN. Next useful bounded work is the editable website-to-public-enquiry journey. Gallery, recurrence, broader staff/customer corrections, devices/accessibility, PWA/offline, real services and release approvals remain separately open.
