Run the feedback backlog as a build list

Triage what the pencil collects: filter it, assign it, close it, and export the current filter set as a checklist you can hand to a developer.

Owned by Venue Manager · 14 steps · about 15 minutes

Why this exists

Notes arrive attached to the thing they are about. A note carries the page path, the route pattern, a fingerprint of the element it was left on, a snippet of what that element said, the viewport width, and — if the author was previewing the site as somebody else — which persona they were looking at. So "this is confusing" arrives already answering what is and where.

That is why the backlog is worth running as a queue rather than reading as a mailbox. Everything a triager normally has to ask for is already on the row.

Why the queue is shared, and the two carve-outs that make it safe

Anyone signed in sees every non-deleted note on any page they can already open — not just their own. A per-person silo produces five copies of "this heading is wrong" and no discussion.

Two carve-outs keep that safe. Notes on staff-only path prefixes — the admin area, the debug console, the scanner — are readable and writable by employees only, because a text snippet harvested from an admin grid can contain other members' data. A non-staff read of one of those pages returns an empty list rather than a refusal, so the endpoint cannot be used to find out which admin pages exist. And one setting narrows every non-staff surface to your own notes only — the switch to flip the day this install holds real user data, with no code change and no deploy.

What you may change, and what you may not

A manager may triage a note but never rewrite its words. Status, priority, category and assignee are yours; the body belongs to its author, or to an admin. An author may resolve or reopen their own note and nothing else. Deleting across authors, and restoring, are admin-only — and deletion is a soft delete, because this module has no hard delete anywhere.

Every one of those changes writes a row to an append-only trail rendered on the note itself. So does every export. Nobody can quietly re-triage history.

Anchors are allowed to go stale, on purpose

A note points at an element by a generated fingerprint. Redesign the page and that element may be gone; the note is then flagged unanchored and kept, never deleted — because "the thing I complained about no longer exists" is usually the signal that it was fixed. Unanchored is therefore a filter you triage, not an error you repair.

The export is the point

The queue exists to become work. Any filter set exports as Markdown, CSV or JSON, and the Markdown one is literally a checklist you can paste into a tracker. Filter to open, high priority, category bug, export, hand it over. That is the loop this feature was built for.

Before you start

  • A venue_manager or admin session for the shared queue. Any signed-in session can leave notes.
  • Some notes to triage. The seed ships four, covering open, resolved, unanchored and a hostile-input probe.
  • The capture gesture itself is a separate workflow — Leave feedback on any part of the app.

Practise with

PersonaEmailPasswordNote
venue_managermanager@club.test manager123triages the shared queue and owns the export
membermember@club.test member123leaves notes and can resolve or reopen their own
adminadmin@club.test admin123the only role that can delete across authors, restore, or edit someone's words

Steps 1 — Member

their manual →

Supplies the backlog, and is the only person besides an admin who may edit their own words.

  1. 1
    A note enters the queue the same way every note does: feedback mode on, hover a block, click its pencil, write, choose a category and a priority. Any signed-in role can do this — member, host, door staff, manager, admin.
    /api/annotations POST annotations
    Expected result A numbered marker on the page and a new row in the shared queue.
    Watch out for Categories are bug, copy, layout, feature and question; priorities are low, normal and high. Whatever the author picks is a starting position, not a verdict — re-categorising is a normal part of triage.

Steps 2–10 — Venue Manager

their manual →
  1. 2
    Open the shared review queue from Feedback Review in the site menu. Start by sorting rather than reading: by status, by priority, by last activity.
    /admin/annotations annotations
    Expected result Every non-deleted note in the app, in one list, with filters above it.
    Watch out for Status and priority sort by pipeline order, never alphabetically — open before acknowledged before in progress, high before normal before low. Sorting by status and getting acknowledged first would be a bug, not a preference.
  2. 3
    Read the page-counts view to find where complaints cluster. One page with nine notes is a different problem from nine pages with one each.
    Expected result Counts per page path, honouring your current filters.
    Watch out for A row whose page is shown as plain text rather than a link is a note pinned to a moment in a recorded workflow clip — that value is the route pattern the step was on, not a page you can open.
  3. 4
    Open one note and read the captured context before the body: the page, the route pattern, the element and its text snippet, the viewport width, and the Viewed as row.
    /admin/annotations/{annotation_id} annotations
    Expected result Enough context to reproduce without asking the author anything.
    Watch out for The viewport width is the most under-used field here. 'The buttons overlap' at 375 pixels and at 1440 are two different tickets, and the note already told you which one it is.
  4. 5
    Triage it: move the status along the pipeline, set priority and category, and assign it to a person.
    /admin/annotations/{annotation_id} POST annotations
    Expected result The change applied and an entry appended to the note's trail.
    Watch out for The pipeline is enforced, not advisory. Open, acknowledged and in progress reach each other and both terminal states; resolved can only go back to open or in progress; won't-fix can only be reopened. An illegal jump is refused, and a stale status — somebody else moved it while your page was open — is refused as a conflict rather than silently winning.
  5. 6
    Reply in the thread instead of editing the note. Ask the question, record the decision, or say what you did.
    /admin/annotations/{annotation_id}/reply POST annotations
    Expected result A reply on the note, visible to its author and to anyone reviewing.
    Watch out for You may never rewrite somebody's words — only the author or an admin can edit a body. That boundary is what keeps the backlog trustworthy: a note you read is what its author actually wrote.
  6. 7
    Filter for anchor health: show the notes whose element can no longer be found. Filter the other way to hide them while you work through live ones.
    /api/annotations/list annotations
    Expected result The unanchored slice, kept rather than discarded.
    Watch out for An unanchored note is usually good news — the thing complained about is gone. Read it, decide whether it was fixed or merely moved, and close it with a reply saying which. Do not treat the flag as data corruption.
  7. 8
    Set the filters you actually want to hand over — open, high, bug — then export. Markdown gives you a checklist; CSV gives you a spreadsheet; JSON gives you everything including the preview persona.
    Expected result A downloaded file covering exactly the rows your filters selected, plus an export entry in the audit trail.
    Watch out for Exports are served as attachments with sniffing disabled, and any CSV cell starting with an equals, plus, minus or at sign is prefixed with an apostrophe. Spreadsheet formula injection through user-written text is a real attack, not a theoretical one.
  8. 9
    Check your own slice too — notes you wrote, notes assigned to you, notes you replied to.
    /my/annotations annotations
    Expected result Your involvement only, filterable by status.
    Watch out for This page ignores the 'own notes only' setting entirely: it is always yours-plus-assigned-plus-replied. Do not use it as a proxy for the backlog — things assigned to other people will not be here.
  9. 10
    Know the two visibility levers you do not own. Staff-only path prefixes are a setting; so is whether non-staff can see each other's notes. Both are platform settings an admin changes.
    Expected result A clear escalation rather than a confusing empty list.
    Watch out for If a member reports 'my note vanished', check whether it was left on a staff-only path — they can see the page but not the notes on it, and the empty list is deliberate rather than broken.

Steps 11–14 — Admin

their manual →

Holds the destructive half: cross-author delete, restore, and the module kill switch.

  1. 11
    Delete a note that should not be in a shared queue — someone's personal data pasted into a body, a duplicate, a test.
    /admin/annotations/{annotation_id}/delete POST annotations
    Expected result The note leaves every list and the deletion is recorded.
    Watch out for Admin only, and it is a soft delete — the row survives and can be listed with an explicit filter. There is no hard delete anywhere in this module, which is deliberate: an audit trail with a hole in it is not an audit trail.
  2. 12
    Restore something deleted in error.
    /admin/annotations/{annotation_id}/restore POST annotations
    Expected result The note returns to the queue with its replies and its trail intact.
    Watch out for Restoration is why the soft delete exists. If you find yourself wanting a hard delete, what you actually want is the 'own notes only' setting turned on so the sensitive content never gets shared in the first place.
  3. 13
    After a workflow clip is re-recorded, list the notes whose step no longer exists.
    Expected result The orphaned clip notes, kept and flagged rather than dropped.
    Watch out for Re-recording re-anchors notes onto the same numbered step where it still exists. What lands here is the genuinely homeless remainder — a step that was removed, which is itself worth knowing.
  4. 14
    Read the module-wide trail when you need to answer 'who changed this, and when' across notes rather than within one.
    Expected result Create, comment, status, priority, category, assign, edit, delete, restore, anchor and export events.
    Watch out for The trail table is append-only at the database level and registered read-only with the data suite, so neither the admin CRUD grid nor a raw shell can tidy it. Exports appear here with no note attached — that is correct, an export is about the queue rather than about one row.