Three backend endpoints under public throttle:30,1:
GET /p/artist/{token} — engagement summary + sections
GET /p/artist/{token}/sections/{section} — form schema + draft values
POST /p/artist/{token}/sections/{section} — section submit
Token resolution via ArtistResolver::fromPortalToken (Step 2). The
master Artist becomes the FormSubmission subject; engagement.event_id
populates form_submissions.event_id per WS-4 denormalisation. Token
mismatches map to 404 (InvalidPortalTokenException), soft-deleted
master artists to 410 Gone (ArtistDeletedException).
Section submit reuses the existing FormBindingApplicator pipeline
(RFC-WS-6 v1.3.1) by dispatching FormSubmissionSectionSubmitted —
no parallel apply path. Drafts are idempotent on
'artist_advance:{engagement_id}', so repeated POSTs find the same
submission. AdvanceSection (engagement-scoped) ↔ FormSchemaSection
bridge: case-sensitive name match against the org's artist_advance
schema; the default seeder names them in lockstep.
Frontend in Session 5 — backend complete here.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>