Skip to content

Domain Relationships

This page records the reusable relationship architecture that emerged from Artist/Event work and now also governs the bounded Event Series hierarchy. It should guide future events, venues, users, admin tables, and relationship-management surfaces without forcing every page to copy one implementation exactly. Event Series authority and hierarchy are detailed in Event Series Architecture.

Large relationship surfaces may also need the query-control, URL-state, and saved-view patterns described in Query Controls And Browsing State.

Choose a relationship surface from the intensity and cardinality of the editing job, not from the join-table shape alone. The stable architecture is a headless relationship capability that preserves identity, authorization, transaction, revision, and query rules; an inline control, secondary surface, or CMS editor may compose that capability differently.

Wavemap’s native add/edit surfaces are optimized for quick one-off workflows. A future Payload CMS integration may own heavier curation, bulk relationship work, richer digital-content management, and repair or provenance review without receiving a separate path around the same domain invariants.

Editing jobLikely surface
Quick, low-cardinality taskInline selection, compact summary, or another lightweight native flow
Medium collection managementSecondary sheet, drawer, focused page, or similar collection surface
Heavy curation or bulk workPayload CMS or another deliberately capable editorial surface

Use normal form controls for scalar entity fields such as name and description. Small relationship sets may be gathered as local draft selections in the same authoring flow, while medium or large sets should behave as collections rather than large removable-card fields.

When a parent create/edit form would otherwise become relationship-heavy, keep it lightweight:

  • Show a compact relationship summary near the relevant section.
  • Include a count badge or accessible count label.
  • Provide an explicit management action such as Manage Artist Events.
  • Avoid rendering a large removable-card list inline with scalar fields.

A collection-management surface may own:

  • Title and count summary.
  • Typeahead or search-driven assignment flow.
  • Current association dataset.
  • Search, filter, sort, and pagination controls when the dataset needs them.
  • Assign and unassign actions.
  • Optional navigation into related entities.

The current artist-events sheet is an intermediate worked example for one editing intensity, not the universal destination for relationship UX. Extract a reusable relationship-management shell only when repeated surfaces prove its contract. Such a shell may own its frame, shared controls, assignment boundaries, and state choreography, but it should not become one rigid table that erases domain differences or constrains a future CMS editor.

Two-sided relationship management is acceptable for trusted admin surfaces when authorization and audit posture support it. For example, the platform may eventually allow editing artist-event associations from an artist page, an event page, or a venue/event-series page. The important part is that each entry point uses the same relationship-management mental model and domain capability, not that every entry point has the same presentation.

Keep relationship-management permission separate from profile editing. Artists are the first worked example: manage-artist-event-relationships allows artist-event association management without implying control over artist profile copy or artist media.

Relationship write contracts should match collection cardinality without weakening the domain invariants beneath them. Wavemap currently uses two deliberate shapes:

  • Event venue, digital-location, external-link, and ticket-link editing replaces the complete desired set because those collections are deliberately small or ordered.
  • Artist–Event editing applies one atomic public-ID delta containing additions and removals from either owning entry point because the relationship can be high-cardinality, filtered, and paginated.

Both shapes resolve public target identities on the server, require active targets for additions, apply the dedicated relationship permission to the source and targets, and execute inside a caller-owned transaction. A removal may resolve an inactive target when the relationship already exists so deactivated data never traps an association that an editor needs to clean up.

Post-create relationship changes use the owning entity revision as a conflict token. The handler locks the active owner, rejects a stale expected revision, applies the relationship change, and advances revision and update provenance exactly once when the persisted join set changes. Idempotent additions and removals return an empty applied change set without manufacturing a revision.

Initial relationships belong in the parent creation transaction when failure should invalidate the new parent. Artist creation accepts optional Event public IDs. Event creation accepts optional Venue and Artist public IDs plus ordered digital-location, external-link, and ticket-link collections. Series creation may accept direct Events only when its structure is already direct-events; Edition creation may accept initial program Events or official Venues. Each parent commits its accepted scalar and database-only relationship state together. Entity media remains a post-create, recoverable workflow because external storage side effects have a different failure and retry boundary.

Active Artist–Event responses publish only the owning entity’s public identity, slug, revision, and the public IDs actually added or removed. These capabilities can serve lightweight Wavemap editors and future Payload batch tooling without exposing database identity or coupling either caller to the other’s presentation.

DELETE /api/v1/events/delete-event/:eventID requires the existing delete-event capability and a positive expectedRevision. It permanently removes the active Event, owned media/link/digital-location rows, and Artist, Venue, direct Series and Edition program associations in one transaction. Related entities survive, including inactive Series and Editions. Being past or cancelled never triggers deletion automatically.

The deletion owner locks the Event first, then obtains all associated Series and Edition locks without waiting. An incomplete lock inventory returns a conflict and rolls back. Series and Edition membership writers hold key-share locks on Event targets through commit, preserving their existing owner-first order while coordinating with deletion. Each affected direct Series and Edition advances its revision exactly once. An Edition’s parent Series does not advance merely because its program changed.

Success returns the deleted Event’s public ID and slug, affected Artist/Venue public IDs, revised Series/Edition identities, and a separate media-cleanup status. Clients remove Event caches and reconcile collections, related previews, Series programs and map views. 409 preserves the current page pending refreshed data and renewed delete intent; 404 means missing/inactive/already deleted. Storage pending status must not invite repeating Event deletion.

Storage cleanup follows commit and uses durable pending recovery. There is no retained Event row, restore token or new durable audit history. Surviving owners keep their existing revision and update provenance; cleanup entries disappear on success.

Domain join tables should be modeled so they can grow into first-class association entities.

The current durable schema pattern is:

  • A surrogate ID UUID primary key for the association row itself.
  • Foreign keys for the participating entities.
  • A separate uniqueness constraint that expresses the current business rule.

Current examples include:

artists_events: unique(artistID, eventID)
events_venues: unique(eventID, venueID)
events_event_series: unique(eventID, eventSeriesID)
event_series_edition_events: unique(eventSeriesEditionID, eventID)
event_series_edition_venues: unique(eventSeriesEditionID, venueID)
users_roles: unique(userID, roleID)
roles_permissions: unique(roleID, permissionID)

Do not use composite primary keys such as (artistID, eventID) for domain association tables. Row identity should stay separate from business uniqueness so the row can later carry metadata without a conceptual reset.

Keep the current pairwise uniqueness rule until the domain introduces a real discriminator. A UUID primary key does not mean duplicate association pairs should be allowed by default. Relax uniqueness only when the application can explain and render the difference, such as:

  • roleType
  • billingOrder
  • appearanceType
  • setNumber
  • Active-row uniqueness after soft delete

Relationship metadata belongs on the association row, not on either parent entity. If artist appearances at events later need billing order, appearance role, notes, provenance, or workflow flags, those fields should live on artists_events.

Domain association rows are the likeliest to grow richer over time. Authorization joins such as users_roles and roles_permissions can stay lean unless auditing, temporal history, or permission-management workflows require more.

New artists_events and events_venues rows record creation time and creator identity. Creator identity remains nullable where historical rows predate provenance. The next likely additive lifecycle fields, when a concrete audit workflow requires them, are:

  • updatedAt
  • updatedByUserID

Soft delete is the main future schema fork. If reversible unassignment becomes important, relationship tables may need removedAt and removedByUserID, plus a uniqueness rule that applies only to active rows. Treat that as a deliberate migration and product decision, not a default table shape.

The following items are intentionally not treated as settled architecture yet:

  • The exact reusable prop/component contract for EntityRelationshipSheet.
  • Which relationship tasks should remain in Wavemap-native quick editors and which should graduate to Payload CMS.
  • Whether relationship removal should stay hard-delete plus audit log or support soft-delete/restore.
  • Which relationship metadata appears first, especially for artist appearances at events.