Voyage · EventFarm Parity Stories

User journeys, end-to-end.

Each story describes one feature of Voyage as a real organizer, attendee, or event-day staff member would experience it — including what success looks like, what failure looks like, and how the page itself supports or fails the user. Trunk stories establish the surfaces; branch stories root in trunks and exercise specific capabilities. Every story is human-audit-ready and machine-consumable by the agent harness that turns it into a Playwright fuzzing run.

Trunk stories

Surfaces of the application. Branches inherit auth + navigation from these.

TRUNK · admin-shell-access
Admin Shell access & navigation
An organizer logs in, lands in the workspace shell, and finds the part of Voyage they came for. Failure modes here are surface-level: authentication, permission, server availability, navigation discoverability.
Organizer Foundation
TRUNK · event-setup
Event Setup hub
Where the organizer configures one event end-to-end: access types, designs, audience, schedule, branding, public page. ~30 branches root here. Roots in admin-shell-access.
Organizer Setup
TRUNK · day-of-operations
Day-of Operations
Kiosk + check-in console + live attendee handling across two surfaces (kiosk.* + staff.*). Offline-mode contract, idempotent two-staff-same-guest pattern, anti-probing for invalid QRs. Roots in admin-shell-access.
Event-day staff Day-of
TRUNK · public-event-page
Public Event Page
The booking-pages app surface. Public guests, no auth shell. 6 failure modes including not-found, archived, draft-treated-as-not-found anti-probing, capacity-full, invite-only-no-token, and og-tags-present for share previews.
Public guest Public

Component stories

Design-system primitives. Tested once with all interaction edge cases. Branches that use a component inherit its contract via usesComponents and don't re-test the fiddly UX bits.

COMPONENT · ui-modal
Modal dialog
Focus trap, esc-closes, backdrop, scroll lock, layered z-index, mobile sheet behavior. The richest interaction primitive in the admin.
Component Inherited by ~50 branches
COMPONENT · ui-text-input
Text input
Validation rendering, autofill detection (no-validation-on-autofill), paste truncation, character counter, focus-ring-visible contract, label always above the field.
Component
COMPONENT · ui-checkbox
Checkbox
Label-click toggles, Space toggles + Enter doesn't, indeterminate aria-checked=mixed, disabled blocks both box and label, focus ring always visible.
Component
COMPONENT · ui-autocomplete
Autocomplete select
Debounce-and-clamp, race-stale-response discard, cursor stability by id not index, no-auto-highlight, three-state Esc, no-results-not-alert. 8 failure modes — the most failure-prone tier-1 primitive.
Component
COMPONENT · ui-form
Form
Submit lifecycle, idempotency-key wiring, busy-state lockout, error rendering (inline + summary), focus-first-error, Enter-vs-Cmd-Enter keyboard semantics.
Component
COMPONENT · ui-toast
Toast
Content-length-aware auto-dismiss timing, hover-pause / focus-pause, max 3 stacked + queue, dedup by id, no-auto-focus-steal, mobile placement that doesn't overlap workspace chrome.
Component
COMPONENT · ui-data-table
Data table
The most-used surface in the admin. Sort round-trips through parent, sticky header doesn't bleed, row-click vs inner-button delegation, page-only vs cross-page select, distinct empty/loading/error states, long-cell truncation, keyboard nav.
Component Inherited by ~30 list-view branches
COMPONENT · ui-pagination
Pagination
Page numbers + prev/next + first/last + page-size, "Showing X–Y of Z" status. Page-size change resets to page 1, current page not clickable, ellipsis non-interactive, empty list hides controls. Total is required — never "?".
Component
COMPONENT · ui-status-pill
Status pill
Closed registry of 24 statuses (draft, registered, ready, failed, bounced, …). Color is never the only differentiator, custom labels override defaults, unknown status falls back to "Unknown" with a warning, prefers-reduced-motion respected.
Component
COMPONENT · ui-search-with-filters
Search with filters
Header above every list. 300ms debounce, Enter flushes, Esc clears. Active filters always visible (no "+2 more" collapse). Clear-all wipes both search and filters. Result count goes skeleton during in-flight, never stale.
Component
COMPONENT · ui-bulk-action-bar
Bulk action bar
Appears when selection > 0. Page-scope vs all-matching scope distinction enforced. Destructive actions always confirm. Pluralization correct. Always shows absolute count, never "many". Bar persists during in-flight action.
Component
COMPONENT · ui-file-uploader
File uploader
File picker + drop zone + per-file progress. Validates size and MIME before upload starts, abort actually aborts (AbortController), retry uses idempotency-key, watchdog timeout marks stuck uploads as failed, partial-failure semantics surfaced, 0-byte and folder drops rejected.
Component
COMPONENT · ui-async-job-tracker
Async job tracker
Polls a background job's lifecycle. Progress clamps at 99% until ready, stuck-in-queued banner after 60s, polling stops on terminal state, race between cancel-and-complete handled, expired countdown never goes negative, request-id always shown on failure for support.
Component Inherited by EF-086, EF-088, EF-089, EF-093
COMPONENT · ui-destructive-confirmation
Destructive confirmation
The "are you sure?" dialog. Friction-by-design: initial focus on Cancel, Enter doesn't confirm, type-to-confirm for high-stakes ops (case-sensitive), async confirm gates the modal, dialog stays open on rejection with inline error.
Component
COMPONENT · ui-date-range-picker
Date range picker
Timezone-honest date selection. ISO strings as source of truth, never silent end-before-start swap (always prompts), DST-safe day enumeration, locale-aware text parsing (en-US vs en-GB), min/max enforced in calendar, presets show their dates before clicking.
Component
COMPONENT · ui-stepper
Stepper / wizard
Multi-step navigation. URL-state mandatory (linkBuilder), back-navigation skips validation (going back is always free), Next validates first, direct-URL-out-of-order redirects to first incomplete step, optional steps with allowSkip, async onStepChange with busy state.
Component
COMPONENT · ui-rich-text-editor
Rich text editor
Schema-bounded editor (output is JSON, never HTML). Paste-from-Word strips inline styles, merge tokens are atomic chips (cursor skips interior), undo/redo groups by operation, link URLs allow-listed (no javascript:), maxLength counts plain-text not markup.
Component
COMPONENT · ui-tabs
Tabs
WAI-ARIA-compliant tabs. Arrow keys auto-activate, disabled tabs skipped during nav, inactive panels unmounted (no display:none state leak), badge=0 hidden, overflow scrolls or wraps but never hides behind a "More" menu, URL-sync via linkBuilder.
Component
COMPONENT · ui-permissions-matrix
Permissions matrix
Subject × ability grid. Implied abilities cascade (granting "edit" implies "read"), revocation cascades when no other source, role presets apply with explicit diff preview, save shows the diff before committing (uses labels, not dot-IDs).
Component
COMPONENT · ui-progress-bar
Progress bar
Determinate / indeterminate. Value clamps to 0..100, NaN renders indeterminate, value never regresses (panic prevention), prefers-reduced-motion drops animation, tone reinforced by icon (not color alone).
Component
COMPONENT · ui-csv-import-preview
CSV import preview
Header→field mapping + per-row validation. Auto-match marked as "auto" so user can verify, commit sends only valid rows, large file commits all rows (not just preview), retry uses idempotency-key, post-commit per-row error report download.
Component

Branch stories — pilot

One per representative EF capability. Each roots in a trunk and focuses on the specific feature's success + failure surface. Component-tier mechanics (modal focus trap, autocomplete debounce, etc.) inherit from the component stories above.

EF-008
Create or copy event
Organizer creates a fresh event or clones a past one. The seemingly-simple one — but the failure modes around copy-from-deleted-source and cross-tenant access have real teeth.
Organizer Planning
EF-018
Invite to RSVP
Private free invitation. 12 failure modes including the dignified-rejection contract (no-leak, no-diagnostic-distinguisher, warm tone, request-invitation CTA), capacity-full waitlist, revoked-mid-flow with composed-message preserved.
Organizer + guest Setup → Public
EF-031
Registration button modal
The public guest's first interaction. 8 failure modes including validation-required-field, email-format-invalid, back-button-closes-modal, network-failure-retry, capacity-full-mid-fill, two-tab-race-idempotent, server-500-with-request-id, already-registered.
Public guest Public
EF-066
QR reader check-in
9 failure modes including idempotent two-staff-same-guest, expired-window with permission-gated force, tampered-QR anti-probing, waitlisted-three-options decision UI, network-drop offline queue.
Event-day staff Day-of
EF-086
Generated reports
Async-job lifecycle. 11 failure modes including job-stuck-queued, job-failed-with-reason, signed-URL-expired, swept-artifact, two-organizers, large-dataset, bounce-indicator, race-window-404, permission-revoked, cancel-mid-run, permission-gated-catalog.
Organizer Closeout

Coming next

The 5-pilot scope is now complete: 4 trunks, 6 components, 5 branches, all lint-clean and harness-runnable. Next, the remaining 95 EF capabilities get codex-bulk-generated against this template, with a manual review pass per batch to deepen failure modes that go shallow. EF-060 (SPF/DKIM masking), EF-024 (promo codes), the EFx live-event modules, native check-in app surface, integrations — each becomes a branch story, each rooted in the appropriate trunk.