Appearance
Admin Panel MVP, round 1: staff sign-in, Access control, Users, Leads and Overview
Purpose. This round corrects the approved Admin Panel design before any of it is built. It applies the owner's decisions of 2026-09-28 and closes every gap the implementation assessment measured. Nothing here is built until the returned design is approved.
- Status: sent and returned 2026-09-28. Its eight items came back mostly resolved; what is still open is round 2, with a verdict per item (QRS-1450). Drafted 2026-09-28. The assessment behind it is Admin Panel MVP assessment; the programme row is QRS-1404.
- Companion prompt, sent in the same round: Account holds, round 1. It covers what a suspended or blocked account looks like to the public and to the account holder, which lives on other surfaces.
- Rule for every later round: any gap found during implementation comes back here as round N+1, is approved, and only then is built. The loop is in the assessment's design-gap loop section.
What was measured, and why each item is a design question
Pulled fresh on 2026-09-28 with DesignSync list_files and get_file:
prototype/admin-panel/Overview.dc.html,Users.dc.html,RBAC.dc.html,Leads.dc.htmlandadmin-shell.js;prototype/platform/users-core.js,segments.js,desk-records.js,ops-signals.js,capabilities.jsandleads-core.js;SCREENS.md.
These were read mechanically rather than from memory.
⚠ Only admin-shell.js, RBAC.dc.html, Users.dc.html, Leads.dc.html, leads-core.js and SCREENS.md were kept on disk. Overview.dc.html, users-core.js, segments.js, desk-records.js, ops-signals.js and capabilities.js were read in full in the authoring session and not saved, so claims about them cannot be re-checked from a local copy. Every file is pulled fresh again before its screen's parity contract (the pull-design skill).
| # | What the design says today (evidence) | Verdict | Tracker |
|---|---|---|---|
| 1 | There is no sign-in screen. Sign-in is signInModal() inside admin-shell.js, drawn over whichever desk was opened. Absent: the set-password link flow, the server outcomes (wrong credentials, no active role, deactivated, too many attempts, network), the submitting state, session expired, signed out elsewhere. The sign-in hint says "at least six characters" while the change-password rules require ten characters, a number, mixed case and a symbol (PW_RULES). A demo role picker sits inside the sign-in flow, and a "Back to the prototype hub" link sits in the profile menu (admin-shell.js:479). | Design needed, first priority | QRS-1405 |
| 2 | The staff lifecycle is claimed, not designed. The sign-in copy says accounts are created and passwords reset "in Access control". RBAC.dc.html has no invite, reset, deactivate or offboard flow. "Assign role" takes a free-text full name. | Design needed | QRS-1406 |
| 3 | Four role models disagree. admin-shell.js ROLES has 7 roles with desk lists. RBAC.dc.html SYSROLES has 10 roles with a module × action matrix. Users.dc.html perms() hardcodes permissions from the demo toggle. leads-core.js ROLES has 5 CRM roles, 11 actions and an own record scope. RBAC MODULES has no users module; crm lacks assign, send, fields, segments and team. Lead owners are the literal OWNERS list. | Design needed | QRS-1407 |
| 4 | Platform staff are mixed with tenant access. RBAC SCOPES include org and workspace, an External Partner agency role, and assignment targets such as a merchant's workspace. | Decided: platform staff only | QRS-1408 |
| 5 | There is no "not built yet" state for unbuilt desks. The Overview reads one aggregate, ops-signals.js, which spans all fourteen desks (it imports eight platform cores and takes the user directory as an injected module), and the MVP builds four desks. Users' record chain and actions and Leads' Send / Consent / Segments open desks that will not exist. capabilities.js already has the right pattern for operator surfaces (the roles and contracts capabilities: a reserved panel naming the store, no disabled control, no date). | Design needed, extending an existing pattern | QRS-1409 |
| 6 | Leads import is a toast ("reuses the audience importer", which belongs to an out-of-scope desk). Won ("signed up and card published") has no step linking the lead to the account it produced. | Design needed | QRS-1411 |
| 7 | Copy and controls: the read-only banners name "Ops" while the read-only role is Auditor; assignment dates are free-text inputs; "Reset password or OTP" does not fit people who sign in with a WhatsApp code; "Two key" erase has no approver surface. | Corrections | QRS-1412 |
Deliberately NOT in this round:
- View as user. The spike measured that a read-only impersonated session cannot be built on this platform (QRS-1418): Dev signs tokens with ES256, and the only supported path creates a full, writable session. The owner decided on 2026-09-28 that it becomes a read-only support view inside the admin panel, with its own ADR (ADR-0038, reserved) and its own later design round. It is not part of this round.
- Anything that sends a message. Communications is out of scope and the platform has no consent store (Leads is pipeline only by owner decision).
- Editing platform policies (Mission Control is out of scope).
- The handbook site itself. It is a documentation site on the shared portal theme. Only its entry points in the shell are in this round.
The prompt
Paste Block 1 and Block 2 together, followed by the PDPR Design Prompt, as the screen coverage mandate directs.
Block 1: the product you are extending
text
YOU ARE EXTENDING AN EXISTING APPLICATION, NOT BUILDING A NEW ONE.
This round corrects the QR setu Admin Panel that already exists in this project, in
prototype/admin-panel/. It is the internal console QR setu's own staff use to run the platform:
the Overview and fourteen desks behind one shell. A staff member must not be able to tell where
the existing panel ends and this round's work begins.
STUDY THESE BEFORE PROPOSING ANYTHING. They are the product you are extending.
prototype/admin-panel/admin-shell.js the chrome every desk loads: nav groups, header, palette,
sign-in modal, change password, deny screen, breakpoints
prototype/admin-panel/Overview.dc.html the command centre, a pure reader of ops-signals.js
prototype/admin-panel/RBAC.dc.html Access control: roles, permissions, assignments,
approvals, audit log
prototype/admin-panel/Users.dc.html the people and accounts desk
prototype/admin-panel/Leads.dc.html Leads & CRM, the sales pipeline the Ops team runs
prototype/admin-panel/ds-base.js the shared base every admin screen imports
prototype/admin-panel/support.js the runtime every admin screen loads
prototype/admin-panel/confirm-delete.js the destructive-action confirm pattern
prototype/admin-panel/qr-toast.js the toast pattern
prototype/admin-panel/leads.spec.md the Leads model and its one rule
prototype/platform/users-core.js the user ecosystem model and its action registry
prototype/platform/leads-core.js the lead model, stages, roles and contact policy
prototype/platform/ops-signals.js the only cross-desk aggregate
prototype/platform/desk-records.js records the desks work on
prototype/platform/capabilities.js what the platform holds yet, and the absent state
prototype/platform/segments.js saved views and segment rules
prototype/platform/controls.js platform policies as data
SCREENS.md the registry; update every row you change
BEFORE ANY SCREEN, PRODUCE TWO LISTS.
REUSED every existing component, module, pattern, token and layout rule you will use
unchanged, naming the file.
NEW anything you must introduce, each with one sentence saying why the existing
pattern genuinely cannot carry it. A new pattern with no justification is a defect.
EVERY NEW SCREEN MUST HAVE A NAMED RELATIONSHIP to an existing screen, navigation path, user
state or workflow. Stay inside prototype/admin-panel/ and prototype/platform/. Import the shared
modules above by name; a new file beside them inherits nothing unless you say so.
Only introduce a new pattern when the use case genuinely requires it, and say why.Block 2: this round
text
ADMIN PANEL, ROUND 1. THE DECISIONS BELOW ARE SETTLED BY THE OWNER. DESIGN TO THEM; DO NOT
REOPEN THEM.
SETTLED FACTS
- The panel lives at its own address, admin.qrsetu.com, separate from the public site.
- Before the panel's own sign-in, a network gate verifies the person's work identity. That
gate is a Cloudflare page and is NOT part of this design.
- Staff sign in with WORK EMAIL AND PASSWORD. There is no sign up, no phone sign-in and no
second factor. Customers and merchants sign in with a WhatsApp code; staff never do.
- Nobody is ever emailed a password. A new staff member, and anyone whose password is reset,
receives an email with a single-use, expiring link that opens a Set your password screen.
- Access control covers QR SETU STAFF ONLY. Organization and workspace scopes and the
External Partner role are removed from this desk (they belong to a later enterprise track).
- Four desks are in scope (Overview, Users, Leads & CRM, Access control), plus the shell and
sign-in. The other eleven stay in the nav but are not built yet.
- Only a SUPER ADMIN manages staff accounts (invite, reset, deactivate). The design's own
role note says a Platform Administrator "cannot manage other admins", so wherever the
copy says "ask a Super Admin or Platform Administrator", it becomes "ask a Super Admin".
- Leads & CRM is a pipeline only: it records, assigns and tracks. It sends no WhatsApp and
captures no consent in this release.
- One password rule everywhere a password is set: at least ten characters, a number, an upper
and a lower case letter, and a symbol. Sign-in itself only checks the fields are filled.
1. STAFF SIGN-IN, THE FIRST SCREEN. Make it a standalone page, not a modal over a desk; nothing
of the panel renders behind it. Suggested: prototype/admin-panel/SignIn.dc.html. Reuse the
brand block and field styling already in signInModal().
States to design, each one visible:
default; submitting; wrong email or password (one generic message that never says which);
too many attempts (wait and try again later; show a time only if the service gives one);
no active role (the person signed in but holds no current assignment, or it expired: say
so and say who can grant access); access removed (the staff account was deactivated);
network or service unavailable (retry);
session ended: ONE state for every reason a session can end (it timed out, they were
signed out everywhere, or their password changed), because the app cannot tell which.
Signing in again returns them to the desk they were on.
Remove from the shipped panel: the "Continue as" role picker in sign-in, and "Back to the
prototype hub" in the profile menu and the sidebar footer.
The prototype still needs to preview roles, so move role choice to a design-tool prop, the
way Users.dc.html exposes demoState.
Keep and align: change your password (profile menu), sign out, and the deny screen for a desk
outside the role.
2. SET YOUR PASSWORD. The screen a staff member reaches from an invite or reset email.
Suggested: prototype/admin-panel/SetPassword.dc.html.
States: first time (invite, greeting by name, the role they were given); reset; link no
longer valid (ONE state: a used link and an expired link cannot be told apart, so do not
design two; say to ask a Super Admin for a new one); success (then
straight into the panel, no second sign-in). The four rules checked live, as in the current
change-password modal.
3. STAFF ACCOUNTS INSIDE ACCESS CONTROL. The lifecycle the sign-in copy already promises:
invite (work email, name, role, permanent or time-bound, a note); pending invite (sent,
expires, resend, revoke); active; deactivated; reactivate (sends a fresh set-password link).
Actions per person: send a password reset link; sign out everywhere; change role;
deactivate with a required reason. Deactivating someone who owns leads must first reassign
those leads, inside the same flow.
Show these refusals in the "not available here" style, each with its sentence:
you cannot change your own access; the last Super Admin cannot be removed or demoted; only
a Super Admin grants Super Admin or Platform Administrator; a Super Admin assignment is
always permanent, never time-bound; invites go only to the work
email domains the network gate admits (today qrsetu.com); an email that already belongs to
a QR setu account cannot be invited, so a staff member needs a separate work email.
"Assign role" picks a real staff member from this list, never a typed name. Its start and
end dates use the in-app picker pattern (see prototype/mobile-console/future-date-picker.js),
never a text input.
A person may hold more than one assignment. Show their effective access as the union, with
each assignment's own window.
4. ONE ROLE MODEL. Today the shell, Access control, Users and Leads each carry their own. Merge
them into Access control's module x action matrix and make it the only source:
- The shell shows a desk only when the role holds view on its module. canOpen() is derived
from the matrix, never a separate desk list.
- Add a users module whose actions match what the Users desk offers in this release:
view, reveal contact details, suspend and reactivate, block and unblock, sign out
everywhere. (Export is reserved in this release.) Name the permission a refusal needs,
as users-core already does.
- Extend crm with the actions Leads uses: assign, manage fields, team view, import, export,
plus a record scope "own leads only" for sales staff.
- Users.perms() and the Leads role prop read the signed-in role; nothing hardcodes access.
- One list of system roles, platform scope only. It includes Sales Manager and Sales
Executive. External Partner is removed. Every role's grants are visible in the matrix.
- Lead owners are staff members who hold a CRM role, picked from the staff list.
In this release the system roles are READ ONLY. Creating, cloning, inheriting or editing a
role, bulk retire and the Approvals queue keep their places as reserved panels (see item 5).
5. NOT BUILT YET, ONE PRESENTATION. Extend capabilities.js with an operator capability for each
desk that is not built in this release (Billing, Subscriptions, Moderation, Communications,
Templates, Affiliates, Ad Manager, Trending, Mission Control, Plans, Workspaces), plus role
editing and approvals, lead messaging and consent, and user segments. Then use its existing
reserved-panel rule everywhere a screen touches one of them:
- Overview: every vital, attention row, map tile, approval count and health row whose desk
is not built becomes a reserved tile naming what is missing. Never a zero, never a guess.
- Users record: chain links and actions that open an unbuilt desk.
- Leads: Send WhatsApp, Ask for consent, Segments, campaign readiness and reachable for
marketing.
- Nav: unbuilt desks stay findable and say "not ready yet". No dead link, no fake screen.
Compose each screen so its release state reads as finished, not as a page of holes.
6. WHAT IS LIVE, SO YOU KNOW WHAT TO DRAW AS REAL.
USERS
- Directory: search, facets, sorts and paging.
- Record: identity, status with the hold reason and who set it, workspaces and their role,
Setu Card status, plan, order count, and last sign-in time (a login fact, kept separate
from activity, as the design already insists).
- Contact details are masked until someone with the reveal permission reveals them, and
every reveal is logged.
- Pulse: registered people, the population split (merchant people, individuals, consumers,
unconverted leads from Leads, staff), paying accounts, new this month.
- Audit tab.
- Actions: suspend and reactivate, block and unblock, sign out everywhere. Each asks for a
reason and writes an audit row.
- Statuses: Active, Suspended, Blocked, and Deleted by the user.
NOT LIVE (reserved): lifecycle bands, Cohorts, Churn, Interventions, Segments, acquisition
source, identity verification, message, plan change, transfer, export and erase.
"View as user" becomes a read-only support view inside this panel, designed in a later
round: keep a reserved row for it on the record.
A hold names WHAT is held: the person, their business, or both (both is the default for a
solo merchant). A hold on the person refuses their sign-in and ends every session. A hold
on the business withdraws its Setu Card and public pages and refuses its changes, while its
team can still sign in. The action sheet asks which, and its copy follows the choice.
Change the suspend and block copy to what this release does, per that choice, and on
reactivation everything returns to how it was. Do not promise payments stop.
The reason a staff member types is kept on QR setu's record and the audit log. The account
holder is NOT shown it in this release; they see one general message. Say that plainly on
the action sheet, where the reason is typed.
A consumer's record shows account facts only, never biodata or chat contents.
LEADS: the whole pipeline is live.
- Overview, Today, Call list and the outcome sheet, List and bulk stage and assign,
Pipeline, Team, Fields, the stage log, lost reasons, duplicates, assignment rules with a
dry run, and masked phone with audited reveal.
- Design an IMPORT flow inside Leads: upload a spreadsheet, map columns to the field
registry, validate with a verdict per row and its original line number, flag duplicates
within the file and against existing leads, preview, commit, then a result summary.
- Moving to WON asks which account the lead became. Search by business name or card address,
and confirm. It is never matched automatically by phone number. Without a link the lead
cannot be marked Won.
- Industry options come from the platform's industry list, not a literal in the file.
- The eight stages stay exactly as designed.
- CRM policies (weekly cap, quiet days and the rest) show their values read only.
OVERVIEW: live signals come only from the desks in this release.
- Staff invites about to expire and assignments ending within 7 days (Access control).
- Overdue follow-ups, unassigned leads and stalled leads per stage (Leads).
- Accounts on hold (Users).
- Workspaces, published Setu Cards and registered people as vitals.
- Sign-in code delivery over WhatsApp as a health row.
- The feed from the audit log.
Everything else is reserved (item 5).
7. SHELL ENTRY POINTS FOR THE OPERATIONS HANDBOOK. The panel carries a read-only handbook at
admin.qrsetu.com/handbook, written for the operations team. Add a Handbook entry to the shell
and a "How this desk works" link on each desk that opens that desk's page. Design only the
entry points; the handbook site itself is not part of this round.
8. COPY AND CONTROLS.
- The read-only banners name the Auditor role.
- The Access control audit log shows a system row "auto-expired time-bound role". An
assignment's end is worked out when access is checked, so nothing is written at the
moment it ends: show expiry as a derived line, never as a recorded event.
- Leads: STALL_DAYS and TERMINAL in leads-core.js are keyed by stage label. Key them by
stage id, so renaming a stage cannot break the funnel.
- "Reset password or OTP" does not apply to people who sign in with a WhatsApp code. Leave
it out of this release's Users actions.
- "Two key" erase is reserved, so no approver surface is needed yet.
- No em dash or en dash in any user-facing copy.
DELIVERABLES
- SignIn and SetPassword as new artboards.
- admin-shell.js, RBAC.dc.html, Users.dc.html, Leads.dc.html and Overview.dc.html revised in
place (keep a _v1 copy where you rebuild).
- capabilities.js, users-core.js, leads-core.js and ops-signals.js updated so every screen
reads one model.
- SCREENS.md rows updated.
- The REUSED and NEW lists first. Then, for every item 1 to 8, a line saying where it now
lives and which states it shows.After it comes back
- The owner says it was passed. Then pull fresh (
list_files, thenget_filefor every changed file) into the scratchpad and diff it against this round's pull after CRLF normalisation. - Give a verdict per item 1 to 8: resolved · still open · new gap. Anything not resolved opens round 2. It is never quietly accepted.
- Once the owner approves: write the parity contracts (
design-system/parity-contracts/admin-*.json, QRS-1420), update the design review pages underdesign-system/screen-reviews/admin-panel/, and only then start increment 1.
Cross-references
- Admin Panel MVP assessment: scope, evidence, the Principal Architect review and the staged plan.
- ADRs, all Proposed:
- Account holds, round 1, the companion prompt.
- Screen coverage mandate, for the process and the PDPR block.