← All stories

BRANCH · ef-039-built-in-guest-fields

Built-in guest information fields

EF-039Persona: OrganizerRoots in: event-setup

Organizers choose which built-in guest fields are collected and required: title, company, address, phone, and country. Voyage has partial substrate because contact schema accepts title, company, position, address, and privacy fields at workers/events/src/routes/guests.ts:25, and public registration accepts custom_fields at workers/events/src/routes/registrations.ts:34; this story exposes the missing admin field-required configuration and attendee rendering parity.

Preconditions

Organizer has edit rights for registration settings on an event in the active tenant.

Happy path / Lifecycle

  1. Open Guest fields from event setup.

    Built-in fields are listed separately from custom questions so auditors can see which data is first-class contact data.

  2. Mark company, phone, and country required.

    Required toggles are explicit checkboxes and the preview updates to show the attendee-facing registration form.

  3. Save.

    The config persists and future guest registrations validate the required built-in fields.

Failure modes

Permission denied at the right boundary

Trigger: viewer attempts to edit built-in field requirements.

Resolution: 403, no PII config leak, and no write.

Cross-tenant isolation

Trigger: tenant A user guesses tenant B registration settings URL.

Resolution: 404 masks existence and does not reveal guest-field configuration.

Soft-delete leaves audit trail

Trigger: organizer removes a field from active collection.

Resolution: field is disabled/soft-deleted from future forms and audit preserves previous required state.

Archive vs delete distinction

Trigger: organizer stops collecting address.

Resolution: archive/disable affects future responses; historical guest data is not destructively deleted from records.

Edit lock during publish

Trigger: publish begins while field config is being saved.

Resolution: publish snapshot wins and stale field config save shows conflict UI.

Audit row on every state change

Trigger: show/required/privacy settings change.

Resolution: audit row records field key, previous state, new state, actor, and timestamp.

Two organizers concurrent

Trigger: one organizer requires phone while another disables phone.

Resolution: second save receives conflict; both sessions refresh to final state.

Undo window for destructive actions

Trigger: organizer disables a field.

Resolution: 10 second undo restores the prior visible/required setting.

Admin required-config gap

Trigger: organizer expects built-in required toggles.

Resolution: gap panel remains visible until the matrix gap is closed.

Attendee rendering gap

Trigger: required country is saved and public registration renders.

Resolution: preview/harness fails until attendee form renders and validates the built-in field.

PII export boundary

Trigger: user without PII permission views guest fields.

Resolution: field labels may show, but collected values are masked and export controls are absent.

Stable test attributes

Visibility teeth. Each attribute must be effectively visible when active.

data-testWherePurpose
guest-fields-pageRouteRoot editor
guest-fields-formPageSettings form
guest-field-rowFormBuilt-in field row
guest-field-visible-checkboxRowCollect field
guest-field-required-checkboxRowRequired field
guest-field-previewPageAttendee form preview
guest-fields-save-ctaFormSave action
guest-fields-undo-toastToastUndo disable
guest-fields-conflict-modalModalConflict
guest-fields-gap-panelPageMissing parity
guest-fields-pii-maskedPreview/exportPII boundary

Agent test plan

- guest-fields-renders
- save-required-fields
- preview-updates
- permission-denied-boundary
- cross-tenant-404
- soft-delete-audit
- archive-delete-distinction
- publish-edit-lock
- audit-row-every-change
- concurrent-organizers-conflict
- destructive-undo-window
- admin-required-config-gap
- attendee-rendering-gap
- pii-export-boundary