Appearance
TT Time Tracker — feature audits
PrimeVue 4 PWA · French. 25 features audited. Totals across this project:
Blocker 10 · High 48 · Medium 118 · Low 57.See the feature queue for the inventory and the project-level findings for architectural root-causes. Severity counts are parsed from each draft's finding headers.
Every feature below links to its full audit.
Accept invite
Blocker 0 · High 4 · Medium 7 · Low 5
The invite flow is functionally sound and gets the two hardest things right: the token is verified server-side before the password form renders (SEC-02 pass, via GET /api/auth/invite-info), and the success state offers an explicit link instead of a ti…
Admin dashboard
Blocker 0 · High 0 · Medium 3 · Low 0
The admin landing page (admin-dashboard, AdminDashboard.vue) is a KPI strip plus an approvals queue, active-punch list and recent-invoices cards. The approvals Table is wired well — it has a real error surface with retry and a proper empty state, and …
API keys
Blocker 0 · High 0 · Medium 4 · Low 2
The API-keys surface is well-built on the security essentials: the created key is shown once behind a :closable="false" dialog with an explicit "copy now" warning, the table shows only keyPrefix... (never the full secret), and both create and revoke are…
Component gallery
Blocker 0 · High 0 · Medium 1 · Low 1
/dev (Dev.vue, 506 lines) is an internal PrimeVue component gallery titled « Composants » — buttons, cards, form fields, tags, a stepper, a demo table, all built from hardcoded French demo data. As a design surface it is fine. The real issue is that it …
Email verification
Blocker 1 · High 1 · Medium 6 · Low 0
VerifyEmail.vue is a small, careful component — it verifies the token before showing any success state and explicitly handles better-auth's result-shaped (non-throwing) errors, so SEC-02 passes and the "false success" trap is already closed. The probl…
Error states
Blocker 0 · High 0 · Medium 1 · Low 2
tt-time-tracker's 404 (NotFound.vue) is the best error surface seen in this batch and the reference-quality 404 the alignment pass was looking for: a clear illustration, an <h1>, human French copy, and — crucially — two real routes out (context-awar…
Hours / time entry
Blocker 1 · High 4 · Medium 9 · Low 3
The screen is visually polished and its layout logic is careful, but the time model underneath it is broken in one specific and consequential way: **four different places compute a duration that wraps past midnight, and the single validator that gates sav…
Integrations
Blocker 0 · High 0 · Medium 4 · Low 3
The Integrations admin screen is a PrimeVue card-per-provider list with a connect/configure Dialog, a per-integration recent-syncs Table, and toast + ConfirmDialog feedback. It is in good shape on the destructive-action path (MSG-05 passes — the disco…
Invoices (admin)
Blocker 2 · High 5 · Medium 8 · Low 2
The invoice review drawer is the most carefully built surface audited so far — deep-linkable, OCR-aware, with a real audit timeline, a proper archive confirmation and correctly sanitised search highlights. Two structural defects undercut it: **two of the si…
Jobs (superadmin)
Blocker 0 · High 1 · Medium 3 · Low 1
The Jobs monitor is a superadmin BullMQ dashboard: stat tiles by status, a table of recent invoice-processing jobs, and a per-job detail dialog with logs. It polls every 5s (TanStack refetchInterval) and — to its credit — wires the shared Table's error/…
My invoices
Blocker 1 · High 3 · Medium 5 · Low 4
The member-facing invoice surface is a well-considered mobile screen — a single prominent capture CTA, a bottom-sheet flow, an SSE-driven live refresh so the OCR result lands without a reload, and a real archive confirmation. Two defects undermine it on the…
Onboarding wizard
Blocker 0 · High 4 · Medium 6 · Low 4
The wizard is well structured on the happy path — five steps, a skip, a per-step save, a French-language summary screen — but it is the one screen in the app the router will not let an admin leave, and its failure paths are all wrong. The final "Configurati…
Organization chooser
Blocker 0 · High 2 · Medium 5 · Low 1
The chooser view itself is small and mostly sound — real <button> rows, a correct <h1>, a visible focus ring — but the organization selection mechanism around it has two serious gaps. A remembered organization id is read straight out of localStorage…
Organizations (superadmin)
Blocker 0 · High 2 · Medium 5 · Low 1
The superadmin Organizations list is a clickable card grid (not the assigned table), and its cards are bare <div @click> — the screen's primary action is mouse-only. The assigned organization-details route (stat cards, delete, settings) has **no in-…
Overview
Blocker 0 · High 1 · Medium 3 · Low 3
The Overview (/admin/overview) is the admin-wide hours table: a filter bar (period + user/project/status), server-computed totals, an infinite-scroll table with batch approve/reject, and per-entry detail modal. It is well built in several respects the bas…
Password reset
Blocker 1 · High 3 · Medium 7 · Low 4
The flow is structurally complete — request form, generic confirmation, token page, success state, "back to sign in" on every step — and it visibly learned from the enumeration problem: the client forces the generic confirmation even when the request throws…
Profile
Blocker 0 · High 0 · Medium 2 · Low 1
profile is a thin, read-only account card: identity, two hours-stats tiles, an org switcher, an admin/user-space toggle, and sign-out. There are no editable fields, so most FORM rules are not-applicable. The two real issues are that a password-based user …
Projects
Blocker 0 · High 5 · Medium 6 · Low 3
The Projects list is in good shape: cards are real <button>s, ListErrorState is wired, and the empty states are properly differentiated per view (search / active / completed / archived) with recovery actions. Almost everything below is on the **deta…
Settings
Blocker 0 · High 0 · Medium 2 · Low 3
The Settings page (org logo, theme, feature toggles, email-sync IMAP config, admins) is well built: the approval-workflow toggle uses the correct "confirmed toggle" variation (a cutoff-date modal that reverts on dismiss), admin removal confirms first (MSG-0…
Sign in
Blocker 2 · High 1 · Medium 6 · Low 2
The sign-in surface is three separate forms behind one route: e-mail + password (LoginChooseMethod), an organization lookup (LoginChooseOrganization) leading to a scoped username + password form (LoginLocal), and a Google button. The markup is clean P…
Syncs
Blocker 0 · High 1 · Medium 2 · Low 1
Syncs is a small admin list: a trigger button, a status table, an empty state and a details modal. The list plumbing is above the project average — Table wires an explicit error/retry state and the empty state has a real CTA, so this screen does not r…
Task lists
Blocker 1 · High 3 · Medium 7 · Low 2
Editing an existing task list cannot be saved at all: ModalTaskList echoes the API's own response object back as the PATCH body, and the API runs a global ValidationPipe with forbidNonWhitelisted: true, so every save is rejected with a 400 and the…
User dashboard
Blocker 0 · High 2 · Medium 4 · Low 4
Dashboard.vue (the « Bilan » tab) is the better-built half of the worker-facing app: unlike its siblings it does have an error surface for its summary fetch, with a real « Réessayer » button. The problem is that the honest surface covers only one of the…
Users
Blocker 1 · High 2 · Medium 7 · Low 3
The Users list and detail screens are among the better-built surfaces in this repo: the table has a real error state with retry, the empty states are context-aware with an action, invite failures are surfaced honestly rather than reported as success, and th…
Vehicles
Blocker 0 · High 4 · Medium 5 · Low 2
Vehicles is a small, tidy admin CRUD screen — it has the ListErrorState + retry surface the worker screens lack, a real archive view, and a shared confirm dialog. The problems are on the edges: the vehicle cards are click-only <div>s so the entire edit/…