Commit Graph

10 Commits

Author SHA1 Message Date
a7ccd2b97e fix(portal-types): clear residual long-tail tsc errors
Resolves the 4 tiptap-independent TypeScript errors that survived
the tiptap 2.27.2 upgrade. All fixes are type-narrowing or type-
annotation refinements; no runtime behavior changes.

Errors fixed:

  - vite.config.ts:50 — TS7006: parameter 'componentName' implicitly
    has an 'any' type.
    Fix: annotate as `(componentName: string)`. The
    unplugin-vue-components resolver always passes a component-name
    string.

  - src/@layouts/types.ts:7 — TS2322 source: Type 'string' is not
    assignable to type 'Lowercase<string>'. Vuexy boilerplate
    constrained `LayoutConfig.app.title` to all-lowercase, which
    rejects "Crewli Portal" in themeConfig.ts. The lowercase
    constraint serves no consumer in our code and was a Vuexy
    template oversight.
    Fix: relax type to `string` at the type definition (root cause).
    No call-site changes needed.

  - src/plugins/iconify/build-icons.ts:19 — TS2307: Cannot find
    module '@iconify/types' or its corresponding type declarations.
    The build:icons postinstall script uses `IconifyJSON` as a type
    annotation. `@iconify/types@2.0.0` was already in the pnpm
    store as a transitive dep of `@iconify/tools` but not hoisted
    to portal's node_modules root.
    Fix: add `@iconify/types` as an explicit dev-dependency.

  - src/@layouts/plugins/casl.ts:51 — TS2345: Argument of type
    '{}' is not assignable to parameter of type 'string'.
    Vue-router types `RouteMeta` loosely; the if-guard on line 50
    narrows truthiness but TS doesn't infer string from `{}`.
    The same pattern on line 55 already uses `// @ts-expect-error`;
    we prefer an explicit `as string` cast at the call site since
    intent is clearer than a suppression comment.
    Fix: cast `targetRoute.meta.action` and `targetRoute.meta.subject`
    to `string` at the `ability.can(...)` call.

vue-tsc errors:
  Pre:  4 own-code (post tiptap upgrade), 0 in node_modules.
  Post: 0 own-code, 0 in node_modules.

apps/portal `pnpm exec vue-tsc --noEmit` now exits clean.

Vitest: 113/113 passing. Build: 8.68s, succeeded.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 04:33:54 +02:00
f7bb8645c4 fix(portal-deps): upgrade @tiptap/* 2.27.1 → 2.27.2 to fix dist resolution
Tiptap 2.27.1 ships a packaging bug: dist/index.d.ts re-exports
from '../src/CommandManager.js' (and 22 similar lines), but those
.js files do not exist — only .ts source. With the project's
moduleResolution: "Bundler" config, vue-tsc falls through to
src/CommandManager.ts and pulls tiptap's entire uncompiled source
tree into the program. skipLibCheck is already true but does NOT
suppress the resulting errors: skipLibCheck only affects .d.ts,
not raw .ts reachable through the import graph.

Tiptap 2.27.2 fixes the dist exports to use sibling-relative paths
(./CommandManager.js), which resolve correctly to the existing
dist/CommandManager.d.ts files. No walk into src/.

The existing ^2.27.1 caret already accepted 2.27.2; pnpm-lock just
froze 2.27.1 from when it was the latest. `pnpm update '@tiptap/*'`
brings all 12 packages to 2.27.2:

  - @tiptap/core 2.27.1 → 2.27.2 (transitive)
  - @tiptap/extension-character-count 2.27.1 → 2.27.2
  - @tiptap/extension-highlight 2.27.1 → 2.27.2
  - @tiptap/extension-image 2.27.1 → 2.27.2
  - @tiptap/extension-link 2.27.1 → 2.27.2
  - @tiptap/extension-placeholder 2.27.1 → 2.27.2
  - @tiptap/extension-subscript 2.27.1 → 2.27.2
  - @tiptap/extension-superscript 2.27.1 → 2.27.2
  - @tiptap/extension-text-align 2.27.1 → 2.27.2
  - @tiptap/extension-underline 2.27.1 → 2.27.2
  - @tiptap/pm 2.27.1 → 2.27.2
  - @tiptap/starter-kit 2.27.1 → 2.27.2
  - @tiptap/vue-3 2.27.1 → 2.27.2

Patch-level upgrade: no API surface change. Drop-in.

vue-tsc errors:
  Pre:  729 total = 22 own-code (incl. 18 downstream tiptap
        TS2339 'Property does not exist on type SingleCommands'
        leaking from TiptapEditor.vue + ProductDescriptionEditor.vue)
        + 707 in node_modules/@tiptap/
  Post: 4 total = 4 tiptap-independent own-code stragglers
        (vite.config.ts, themeConfig.ts, casl.ts, build-icons.ts)
        + 0 in node_modules

Vitest: 113/113 passing. Build: 8.69s, succeeded.

The 4 remaining own-code errors are addressed in the next commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 04:30:19 +02:00
5771a678ef chore: install ts-reset in both portal and app SPAs
Installs @total-typescript/ts-reset 0.6.1 as a dev-dependency in
apps/portal/ and apps/app/. Patches TypeScript's loosest default
types: Array.filter(Boolean) returns non-nullable, JSON.parse
returns unknown, fetch().json() returns unknown, Map.get() strict,
etc.

Configuration: src/reset.d.ts in each SPA imports the reset. Both
tsconfig.json files already include ./src/**/* so the .d.ts is
picked up automatically — no tsconfig edits needed.

Issues surfaced during install:
  - apps/app — 0 pre-install tsc errors in own code; install
    surfaced 2 errors in src/stores/useImpersonationStore.ts
    (both from JSON.parse on sessionStorage content returning
    unknown instead of any). Fixed inline at lines 19 + 123 via
    `as ImpersonationState` casts that make the existing
    trust-in-sessionStorage explicit. Backlog entry
    TECH-TS-IMPERSONATION tracks proper runtime shape validation.
  - apps/portal — 22 pre-existing tsc errors in own code (mostly
    tiptap editor components — tracked as TECH-TS-PORTAL-TSC,
    unrelated to ts-reset). Zero new errors in portal's own code.
    4 additional errors surfaced in tiptap's uncompiled node_modules
    .ts sources (third-party); left as-is.

Neither SPA achieves `tsc --noEmit` clean today — pre-existing
state unrelated to this work package. Build + vitest are the
actual working gates and both remain green:
  - apps/portal: vitest 113/113 passing; production build succeeds
  - apps/app:    (no vitest setup — tracked as TECH-APP-VITEST);
                 production build succeeds

Documentation: /dev-docs/FRONTEND-TOOLING.md added; CLAUDE.md
quality-gates updated.

Backlog: TECH-TS-IMPERSONATION (runtime validation of stored
impersonation state), TECH-TS-PORTAL-TSC (pre-existing portal tsc
errors), TECH-APP-VITEST (Vitest coverage for apps/app).

No production behavior change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 03:58:11 +02:00
9256c05db0 feat(portal): implement TAG_PICKER, AVAILABILITY_PICKER, SECTION_PRIORITY field types
- FieldTagPicker: VAutocomplete multiple with grouped category slots,
  empty/null category normalised to "Overig", empty-state info alert
  when the server delivers no tags.
- FieldAvailabilityPicker: date-grouped checkbox list, festival-aware
  via usePublicFormTimeSlots. Event-name subheaders only surface when
  the time-slots span multiple events. Time format strips seconds.
- FieldSectionPriority: tap-to-rank + drag-to-reorder via vuedraggable
  for desktop; mobile tap-only. Renumbers priorities on every mutation.
  Self-heals malformed modelValue. UI soft cap via
  validation_rules.max_priorities clamped to the backend hard cap of 5.
- FieldRenderer: three new types removed from isStubbed.
- publicFormInjection: page-level provide/inject for the public token.
- IdentityMatchBanner: prefers backend-provided Dutch copy with
  frontend defaults as defensive fallback.
- FormConfirmation wires the banner inline.
- usePublicFormTimeSlots and usePublicFormSections TanStack composables.
- 40 new Vitest assertions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 20:00:40 +02:00
4074dce402 feat(portal): public-form component architecture
Replace monolithic register/[eventSlug].vue with composable field
renderer, conditional-logic engine, stepper, and per-field components
driven by Form Builder schema. Adds flatpickr for date fields.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 17:20:59 +02:00
0be2956ea4 feat: MFA frontend with auth page restyling, challenge screen, and setup wizard
- Restyle organizer auth pages: Dutch text, remove placeholder social login
- Restyle portal auth pages to Vuexy v1 centered card pattern with decorative shapes
- MFA challenge card component with VOtpInput, method tabs, backup code input,
  trusted device checkbox, and session countdown timer
- Login pages handle mfa_required response with device fingerprint header
- Security settings page with TOTP setup (QR code), email setup, disable MFA,
  backup codes regeneration, and trusted devices management
- Portal profile page includes MFA security section
- Admin user detail page shows MFA status with reset button
- MFA enforcement route guard redirects to security settings when required
- Device fingerprint utility for trusted device identification
- MFA types, composables with TanStack Query for both apps

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 21:32:17 +02:00
b8286d6a84 security: round 4 — frontend hardening (deps, XSS, cookie security)
Vulnerable dependencies upgraded:
- Backend: league/commonmark >=2.8.2 (HTML injection bypass),
  phpunit/phpunit >=11.5.50, laravel/tinker (psysh LPE)
- Frontend: axios 1.13→1.15 (SSRF + metadata exfiltration),
  @casl/ability updated (prototype pollution)
- Removed swiper from all 3 apps (prototype pollution CVE,
  only used in Vuexy demo pages)

XSS vectors removed:
- Deleted Vuexy demo pages with v-html rendering API data:
  help-center/article, academy/course-details
- Deleted all front-pages (landing, pricing, checkout, payment) —
  Vuexy marketing template, not Crewli business logic
- Deleted swiper demo components and views
- Fixed admin main.ts: replaced innerHTML with template literal
  with safe DOM construction using textContent

Cookie security:
- Added SameSite=Strict and Secure flags to admin cookie defaults

Cleanup:
- Removed swiper SCSS from all 3 apps
- Removed swiper custom element config from all 3 vite configs
- Portal localStorage cleanup verified: reset() clears all keys,
  called on both explicit logout and 401 interceptor

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 07:15:00 +02:00
3400e4cc7e feat(portal): multi-step volunteer registration form with public event endpoint
- Add GET /api/v1/public/events/{slug}/registration-data endpoint for fetching
  event sections and time slots without auth
- Create 5-step registration form: personal info, details, motivation, section
  preferences, availability
- VeeValidate + Zod validation per step with Dutch error messages
- Auth-aware: pre-fills name/email for authenticated users
- Mobile responsive with custom chip-based step indicator
- Success page with contextual actions (dashboard vs login)
- Types, composable (TanStack Query), and Zod schemas

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 18:41:20 +02:00
fda161ee09 chore: align migrations, docs, and frontends with crewli.app setup
- Replace dated migrations with ordered 2026_04_07_* chain; fold users update into base migration
- Update OrganisationScope, AppServiceProvider, seeders, api routes, and .env.example
- Refresh Cursor rules, CLAUDE.md, Makefile, README, and docs (API, SCHEMA, SETUP)
- Adjust admin/app/portal HTML, packages, api-client, events types, and theme config
- Update docker-compose and VS Code settings; remove stray Office lock files from resources

Made-with: Cursor
2026-04-07 10:45:34 +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