f5a9e491ce
feat(primevue): add Icon component and mount Toast + ConfirmDialog services
...
Two additions complete the F3 runtime scaffolding:
apps/app/src/components/Icon.vue — generic Iconify renderer wrapping
@iconify/vue's <Icon> component. F4 migration substitutes
<VIcon icon="tabler-X" /> with <Icon name="tabler-X" /> at call-sites,
producing real SVG output and using the existing Crewli "tabler-*"
naming convention. Props: name (required, e.g. "tabler-eye"), optional
size. The component avoids @iconify/vue's auto-import for clarity at
call-sites.
apps/app/src/App.vue — mounts <Toast /> and <ConfirmDialog /> at the
template root inside VLocaleProvider. Both render alongside the
existing VSnackbar and VDialog confirm patterns during the F3–F4
parallel-mode window. F4 sub-packages migrate call-sites to PrimeVue's
useToast() / useConfirm() composables.
UnoCSS-style i-tabler-* utility-class rendering (RFC AD-5 v1.0 wording)
is not adopted — UnoCSS is not installed in the Crewli stack. The
RFC will be aligned in B9.
Verification:
- pnpm typecheck — clean.
- pnpm test — 402 tests pass unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-11 01:06:11 +02:00
b4f5bbe7c2
fix(app): resolve Bucket A/C/D lint items (trivial / style / Vuetify class)
...
WS-3 session 1b-ii Task 4 (audit Buckets A, C, D — 26 items resolved
this commit; 24 indent items in useTimeSlotDropdown.ts remain — see
deviations).
Bucket A — Trivial fixes (12 items resolved):
- A.1: second-pass eslint --fix on App.vue resolved 4 multi-attribute
warnings. AppKpiCard / PortalLayout / PublicLayout
lines-around-comment items were attempted via blank-line addition,
but that introduced an equal number of vue/block-tag-newline
errors (the rules conflict at the SFC <script>-tag boundary). The
blank-line additions were reverted; net-zero, the 3 items remain
for a 1b-iii .eslintrc.cjs override decision.
- A.3: 6 unused-imports / unused-vars manual deletes:
* OrganisationSwitcher.vue: removed orphan toggleMenu() function
* CreateShiftDialog.vue: removed unused 'scenario' from destructure
* pages/events/[id]/time-slots/index.vue: removed unused 'event'
slot scope binding (template <#default="{ event }"> → <#default>)
* pages/organisation/companies.vue: removed unused authStore
declaration + import
* pages/platform/activity-log/index.vue: removed unused
search/searchDebounced pair
* PersonDetailPanel.vue:77: removed redundant single-statement
if-braces (curly autofix that the original pass didn't reach)
Bucket C — Style preference (8 items resolved):
- DismissFailureDialog.vue:43: collapsed two consecutive `if cond return false`
branches into `return !(cond)`
- FormFailureDetail.vue:44: replaced `void clipboard.writeText(...)` with
`clipboard.writeText(...).catch(() => {})` — fire-and-forget with
silent rejection (the no-void rule wants the void operator gone;
.catch() handles it semantically).
- AssignShiftDialog.vue:40-46: hasOverlapWarning collapsed from
always-false branching to `computed(() => false)` (the early-return
was dead code; backend enforces the constraint).
- SectionsShiftsPanel.vue:333 + registration-fields.vue:335: rewrote
`:delay-on-touch-only="true"` to attribute-shorthand `delay-on-touch-only`.
- AssignPersonDialog.vue:120-128: collapsed two `if outer { if inner ... }`
pairs into single `if (outer && inner)` form (sonarjs/no-collapsible-if).
- useImpersonationStore.ts:99-104: collapsed the same nested-if pattern
into `if (!data.data.active && state.value)`.
Bucket D — Vuetify utility class rename (5 items, 3 files):
- ml-1 → ms-1 (PersonDetailPanel:271, SectionsShiftsPanel:357,
AssignPersonDialog:496)
- pl-4 → ps-4 (AssignPersonDialog:457)
- ml-auto → ms-auto (AssignPersonDialog:471)
LTR/RTL-aware Vuetify utilities, matching the Vuexy reference idiom.
Tests + typecheck verified green.
Lint baseline: 62 → 36.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com >
2026-04-29 14:20:34 +02:00
4df668b5b8
feat: replace token-based impersonation with enterprise-grade header-based system
...
Replaces the insecure token-in-localStorage approach with a header-based
impersonation system backed by cache sessions and MFA verification.
Key changes:
- New impersonation_sessions audit table (immutable, ULID PK)
- MFA verification required to start impersonation (TOTP/email/backup)
- X-Impersonate-User header + HandleImpersonation middleware
- Per-request auth context swap (admin session never modified)
- IP pinning, sensitive route blocking, no nesting, sliding 60-min TTL
- Activity log auto-tagged with impersonated_by during sessions
- Frontend: sessionStorage, BroadcastChannel sync, countdown timer
- ImpersonateDialog with reason + MFA verification flow
- 26 comprehensive tests covering core, middleware, audit, lifecycle
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com >
2026-04-16 02:42:53 +02:00
37fecf7181
fix: auth race condition on refresh, section edit dialog, time slot duplicate, autocomplete disable
...
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com >
2026-04-10 11:16:22 +02:00
c417a6647a
feat(app): auth, orgs/events UI, router guards, and dev tooling
...
- Add Sanctum auth flow (store, composables, login, axios interceptors)
- Add dashboard, organisation list/detail, events CRUD dialogs
- Wire router guards, navigation, organisation switcher in layout
- Replace Vuexy @db types in NavSearchBar; add @iconify/types; themeConfig title typing
- Vuetify settings.scss + resolve configFile via fileURLToPath; drop dead path aliases
- Root index redirects to dashboard; fix events table route name
- API: DevSeeder + DatabaseSeeder updates; docs TEST_SCENARIO; corporate identity assets
Made-with: Cursor
2026-04-07 21:51:10 +02:00
1cb7674d52
refactor: align codebase with EventCrew domain and trim legacy band stack
...
- Update API: events, users, policies, routes, resources, migrations
- Remove deprecated models/resources (customers, setlists, invitations, etc.)
- Refresh admin app and docs; remove apps/band
Made-with: Cursor
2026-03-29 23:19:06 +02:00