@go-labs-sg/rsvp 0.6.1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # RSVP CLI (`rsvp`)
1
+ # Registration CLI (`rsvp`)
2
2
 
3
- JSON-first command-line access to RSVP organizations, events, guests, check-in, payments, reporting, retention, and administrative operations.
3
+ JSON-first command-line access to Registration organizations, events, guests, check-in, payments, reporting, retention, and administrative operations.
4
4
 
5
5
  ## Runtime and installation
6
6
 
@@ -49,11 +49,11 @@ rsvp auth status
49
49
  rsvp auth whoami
50
50
  ```
51
51
 
52
- `rsvp auth login` opens RSVP in the system browser. Sign in through RSVP's normal email one-time-password flow if needed, verify that the displayed device code matches the terminal, then click **Authorize CLI**. Existing browser sessions skip another email-code prompt but never skip explicit CLI approval.
52
+ `rsvp auth login` opens Registration in the system browser. Sign in through Registration's normal email one-time-password flow if needed, verify that the displayed device code matches the terminal, then click **Authorize CLI**. Existing browser sessions skip another email-code prompt but never skip explicit CLI approval.
53
53
 
54
- RSVP CLI access is limited to global administrators. The server rechecks the account's current global role and ban state when issuing, refreshing, and authenticating CLI credentials, so removing the admin role immediately blocks further CLI access.
54
+ Registration CLI access is limited to global administrators. The server rechecks the account's current global role and ban state when issuing, refreshing, and authenticating CLI credentials, so removing the admin role immediately blocks further CLI access.
55
55
 
56
- The CLI polls automatically and stores only RSVP-issued credentials through `Bun.secrets`. It does not store browser or email-OTP credentials and has no API-key or environment-variable fallback. Use `rsvp auth logout` to revoke the remote session and remove its local credential. For SSH or containers, pass `--no-browser` and open the printed URL on another device.
56
+ The CLI polls automatically and stores only Registration-issued credentials through `Bun.secrets`. It does not store browser or email-OTP credentials and has no API-key or environment-variable fallback. Use `rsvp auth logout` to revoke the remote session and remove its local credential. For SSH or containers, pass `--no-browser` and open the printed URL on another device.
57
57
 
58
58
  The default API is `https://rsvp.getout.events`. Override it with `RSVP_API_URL` or `--api-url`; non-local overrides must use HTTPS.
59
59
 
@@ -90,6 +90,21 @@ rsvp event flow menu version create \
90
90
  To version an existing menu, use `"menu":{"mode":"EXISTING","menuId":"..."}`
91
91
  in the payload and keep the event ID as `--target`.
92
92
 
93
+ Create a new immutable version of an existing consent document with the same
94
+ event target. Rich text is optional; when supplied, `content` is derived from
95
+ its visible text and stored as the legacy plain-text fallback.
96
+
97
+ ```sh
98
+ rsvp event flow consent version create \
99
+ --allow-state-change \
100
+ --target evt_123 \
101
+ --payload '{"organizationId":"org_123","eventId":"evt_123","document":{"mode":"EXISTING","documentId":"consent_123"},"contentRichText":{"json":{"type":"doc","content":[{"type":"paragraph","content":[{"type":"text","text":"I agree to the terms."}]}]},"html":"<p>I agree to the terms.</p>"}}'
102
+ ```
103
+
104
+ Creating a consent version does not change a registration draft or publish a
105
+ flow. Reference the returned `version.id` from the draft's `CONSENT` block in
106
+ a separate revision-checked draft save.
107
+
93
108
  Reference the returned `version.id` from the draft's `MENU_SELECTION` blocks,
94
109
  then save with `event flow draft save`, `--allow-state-change`, and the event ID
95
110
  as `--target`. Include the latest draft revision as `expectedRevision`; nested
@@ -113,7 +128,79 @@ rsvp check-in by-reference \
113
128
  --payload '{"organizationId":"org_123","eventId":"evt_123","referenceCode":"ABC123"}'
114
129
  ```
115
130
 
116
- High-impact payment and retention commands remain protected by their matching financial, deletion, external-write, and sensitive-data gates. The API always re-evaluates the authenticated user's current RSVP role, organization membership, event assignment, and resource permissions.
131
+ High-impact payment and retention commands remain protected by their matching financial, deletion, external-write, and sensitive-data gates. The API always re-evaluates the authenticated user's current Registration role, organization membership, event assignment, and resource permissions.
132
+
133
+ ## Seating updates
134
+
135
+ `event seating layout update` moves tables, changes table geometry, and can save a floor plan. It requires `--allow-state-change`; its `--target` must match the payload's top-level `eventId`, not a nested table or seat-map ID:
136
+
137
+ ```sh
138
+ rsvp event seating layout update \
139
+ --allow-state-change \
140
+ --target evt_123 \
141
+ --payload '{"organizationId":"org_123","eventId":"evt_123","tables":[{"tableId":"table_123","x":12,"y":8,"rotation":0}]}'
142
+ ```
143
+
144
+ `event seating table update` changes a table label or capacity. Because reducing capacity removes seats, it always requires both `--allow-state-change` and `--allow-delete`; its `--target` must match the payload's top-level `tableId`, including for label-only updates:
145
+
146
+ ```sh
147
+ rsvp event seating table update \
148
+ --allow-state-change \
149
+ --allow-delete \
150
+ --target table_123 \
151
+ --payload '{"organizationId":"org_123","eventId":"evt_123","tableId":"table_123","label":"Table 1"}'
152
+ ```
153
+
154
+ ## Audience tiers
155
+
156
+ Audience tiers control which invitees can use a seat or table. List the tiers and their current invitee, table, and seat counts with:
157
+
158
+ ```sh
159
+ rsvp event audience-tier list \
160
+ --organization-id org_123 \
161
+ --event-id evt_123
162
+ ```
163
+
164
+ Create a tier with the event as the approval target, then update a tier by its own ID:
165
+
166
+ ```sh
167
+ rsvp event audience-tier create \
168
+ --allow-state-change \
169
+ --target evt_123 \
170
+ --payload '{"organizationId":"org_123","eventId":"evt_123","label":"VIP","description":"Executive guests"}'
171
+
172
+ rsvp event audience-tier update \
173
+ --allow-state-change \
174
+ --target tier_123 \
175
+ --payload '{"organizationId":"org_123","eventId":"evt_123","tierId":"tier_123","label":"VIP","active":true}'
176
+ ```
177
+
178
+ For tables and seats, `audienceTierId: null` means Everyone; a tier ID permits only invitees in that exact tier. For invitees, `audienceTierId: null` removes membership (Unassigned), so their party can use only Everyone seats. Invitee assignment applies to the whole party, so bulk assignment uses up to 500 invitee IDs and targets the event:
179
+
180
+ ```sh
181
+ rsvp event invitee tier update \
182
+ --allow-state-change \
183
+ --target evt_123 \
184
+ --payload '{"organizationId":"org_123","eventId":"evt_123","inviteeIds":["invitee_123","invitee_456"],"audienceTierId":"tier_123"}'
185
+ ```
186
+
187
+ The existing `people invitee list` command accepts `audienceTierId` in its JSON payload: omit it for all people, use a tier ID to filter membership, or `null` for Unassigned. Listing people requires `--ack-sensitive-data`.
188
+
189
+ Set table tiers in bulk with up to 200 table IDs. Set seat tiers with up to 500 seat IDs. Seats inherit their table's tier when `inheritFromTable` is true; when it is false, include `audienceTierId` (including `null` for everyone). Use `resetSeatOverrides: true` on a table update when existing seat overrides should be cleared:
190
+
191
+ ```sh
192
+ rsvp event seating table tier update \
193
+ --allow-state-change \
194
+ --target evt_123 \
195
+ --payload '{"organizationId":"org_123","eventId":"evt_123","tableIds":["table_123"],"audienceTierId":"tier_123","resetSeatOverrides":true}'
196
+
197
+ rsvp event seating seat tier update \
198
+ --allow-state-change \
199
+ --target evt_123 \
200
+ --payload '{"organizationId":"org_123","eventId":"evt_123","seatIds":["seat_123"],"inheritFromTable":false,"audienceTierId":null}'
201
+ ```
202
+
203
+ These commands update setup and assignment data only. They do not delete seats, cannot unseat an occupied seat, and should be run before the event is live; live seating modifications remain unavailable.
117
204
 
118
205
  ## Reusable event configurations
119
206
 
package/dist/index.js CHANGED
@@ -19216,6 +19216,13 @@ var commands = {
19216
19216
  scope: "event",
19217
19217
  summary: "List the menus, consent documents, images, and seat maps available to the registration flow."
19218
19218
  },
19219
+ "event flow consent version create": {
19220
+ effects: ["state-change"],
19221
+ operation: (api2, input2) => api2.eventFlow.createConsentVersion.mutate(input2),
19222
+ payloadOnly: true,
19223
+ targetKey: "eventId",
19224
+ summary: "Create an immutable event consent version (--payload JSON)."
19225
+ },
19219
19226
  "event flow menu version create": {
19220
19227
  effects: ["state-change"],
19221
19228
  operation: (api2, input2) => api2.eventFlow.createMenuVersion.mutate(input2),
@@ -19455,7 +19462,19 @@ var commands = {
19455
19462
  summary: "Update a user's global role (--payload JSON)."
19456
19463
  }
19457
19464
  };
19458
- var payloadCommand = (operation, summary, effects = []) => ({ effects, operation, payloadOnly: true, summary });
19465
+ var payloadCommand = (operation, summary, effects = [], targetKey) => ({
19466
+ effects,
19467
+ operation,
19468
+ payloadOnly: true,
19469
+ summary,
19470
+ targetKey
19471
+ });
19472
+ var eventScopeQueryCommand = (operation, summary) => ({
19473
+ effects: [],
19474
+ operation,
19475
+ scope: "event",
19476
+ summary
19477
+ });
19459
19478
  Object.assign(commands, {
19460
19479
  "payment configure": payloadCommand((api2, input2) => api2.payment.configureEventPayment.mutate(input2), "Configure event payments (--payload JSON).", ["external-write", "financial-write", "state-change"]),
19461
19480
  "payment checkout create": payloadCommand((api2, input2) => api2.payment.createCheckout.mutate(input2), "Create the caller's payment checkout (--payload JSON).", ["external-write", "financial-write", "state-change"]),
@@ -19470,22 +19489,32 @@ Object.assign(commands, {
19470
19489
  "admission identity-exception resolve": payloadCommand((api2, input2) => api2.admission.resolveIdentityException.mutate(input2), "Resolve an identity exception (--payload JSON).", ["sensitive-data", "state-change"]),
19471
19490
  "audit list": payloadCommand((api2, input2) => api2.audit.listEventActivity.query(input2), "List event audit activity (--payload JSON).", ["sensitive-data"]),
19472
19491
  "event check-in qr": payloadCommand((api2, input2) => api2.event.checkInByQr.mutate(input2), "Check in using a QR token (--payload JSON).", ["state-change"]),
19492
+ "event background upload create": payloadCommand((api2, input2) => api2.event.createBackgroundUpload.mutate(input2), "Create a background-image upload URL (--payload JSON).", ["external-write", "state-change"]),
19493
+ "event background update": payloadCommand((api2, input2) => api2.event.updateBackground.mutate(input2), "Set or clear an attendee background image (--payload JSON).", ["state-change"]),
19473
19494
  "event walk-in create": payloadCommand((api2, input2) => api2.event.createWalkIn.mutate(input2), "Create a walk-in registration (--payload JSON).", ["sensitive-data", "state-change"]),
19474
19495
  "event seating table create": payloadCommand((api2, input2) => api2.event.createSeatTable.mutate(input2), "Create a seating table (--payload JSON).", ["state-change"]),
19475
19496
  "event seating table delete": payloadCommand((api2, input2) => api2.event.deleteSeatTable.mutate(input2), "Delete a seating table (--payload JSON).", ["delete", "state-change"]),
19497
+ "event seating layout update": payloadCommand((api2, input2) => api2.event.updateSeatTableLayout.mutate(input2), "Update the seating layout and floor plan (--payload JSON).", ["state-change"], "eventId"),
19498
+ "event seating table update": payloadCommand((api2, input2) => api2.event.updateSeatTable.mutate(input2), "Update a seating table (--payload JSON).", ["delete", "state-change"], "tableId"),
19499
+ "event audience-tier list": eventScopeQueryCommand((api2, input2) => api2.event.listAudienceTiers.query(input2), "List event audience tiers and assignment counts."),
19500
+ "event audience-tier create": payloadCommand((api2, input2) => api2.event.createAudienceTier.mutate(input2), "Create an event audience tier (--payload JSON).", ["state-change"], "eventId"),
19501
+ "event audience-tier update": payloadCommand((api2, input2) => api2.event.updateAudienceTier.mutate(input2), "Update an event audience tier (--payload JSON).", ["state-change"], "tierId"),
19502
+ "event invitee tier update": payloadCommand((api2, input2) => api2.event.setInviteeAudienceTier.mutate(input2), "Set an audience tier for whole invitee parties (--payload JSON).", ["state-change"], "eventId"),
19503
+ "event seating table tier update": payloadCommand((api2, input2) => api2.event.setTableAudienceTier.mutate(input2), "Set an audience tier for seating tables (--payload JSON).", ["state-change"], "eventId"),
19504
+ "event seating seat tier update": payloadCommand((api2, input2) => api2.event.setSeatAudienceTier.mutate(input2), "Set or inherit an audience tier for seating seats (--payload JSON).", ["state-change"], "eventId"),
19476
19505
  "event field deactivate": payloadCommand((api2, input2) => api2.event.deactivateFieldDefinition.mutate(input2), "Deactivate an event field (--payload JSON).", ["delete", "state-change"]),
19477
19506
  "event field upsert": payloadCommand((api2, input2) => api2.event.upsertFieldDefinition.mutate(input2), "Create or update an event field (--payload JSON).", ["sensitive-data", "state-change"]),
19478
19507
  "event check-ins export": payloadCommand((api2, input2) => api2.event.exportCheckIns.mutate(input2), "Export check-ins (--payload JSON).", ["sensitive-data", "state-change"]),
19479
19508
  "event registrations export": payloadCommand((api2, input2) => api2.event.exportRegistrations.mutate(input2), "Export registrations (--payload JSON).", ["sensitive-data", "state-change"]),
19480
- "event rsvp mine": payloadCommand((api2, input2) => api2.event.getMyRsvp.query(input2), "Get the caller's RSVP (--payload JSON).", ["sensitive-data"]),
19509
+ "event rsvp mine": payloadCommand((api2, input2) => api2.event.getMyRsvp.query(input2), "Get the caller's registration (--payload JSON).", ["sensitive-data"]),
19481
19510
  "event people overview": payloadCommand((api2, input2) => api2.event.getPeopleOverview.query(input2), "Get people operations overview (--payload JSON).", ["sensitive-data"]),
19482
19511
  "event reminder counts": payloadCommand((api2, input2) => api2.event.getReminderSegmentCounts.query(input2), "Get reminder segment counts (--payload JSON).", ["sensitive-data"]),
19483
- "event rsvp manifest": payloadCommand((api2, input2) => api2.event.getRsvpManifest.query(input2), "Get the caller's RSVP manifest (--payload JSON).", ["sensitive-data"]),
19512
+ "event rsvp manifest": payloadCommand((api2, input2) => api2.event.getRsvpManifest.query(input2), "Get the caller's registration manifest (--payload JSON).", ["sensitive-data"]),
19484
19513
  "event seating availability": payloadCommand((api2, input2) => api2.event.getSeatAvailability.query(input2), "Get seat availability (--payload JSON)."),
19485
19514
  "event realtime-token issue": payloadCommand((api2, input2) => api2.event.issueRealtimeToken.mutate(input2), "Issue a realtime token (--payload JSON).", ["sensitive-data", "state-change"]),
19486
19515
  "event mine list": payloadCommand((api2, input2) => api2.event.listMyEvents.query(input2), "List the caller's events (--payload JSON)."),
19487
19516
  "event reminder list": payloadCommand((api2, input2) => api2.event.listReminderSegments.query(input2), "List reminder segments (--payload JSON).", ["sensitive-data"]),
19488
- "event rsvp submit": payloadCommand((api2, input2) => api2.event.submitRsvp.mutate(input2), "Submit the caller's RSVP (--payload JSON).", ["sensitive-data", "state-change"]),
19517
+ "event rsvp submit": payloadCommand((api2, input2) => api2.event.submitRsvp.mutate(input2), "Submit the caller's registration (--payload JSON).", ["sensitive-data", "state-change"]),
19489
19518
  "event setup step update": payloadCommand((api2, input2) => api2.event.updateSetupStep.mutate(input2), "Update one event setup step (--payload JSON).", ["state-change"]),
19490
19519
  "organization access check": payloadCommand((api2, input2) => api2.organization.checkOrganizationAccess.query(input2), "Check organization access (--payload JSON)."),
19491
19520
  "organization manage-access check": payloadCommand((api2, input2) => api2.organization.checkOrganizationManageAccess.query(input2), "Check organization management access (--payload JSON)."),
@@ -19522,7 +19551,7 @@ var getCommandManifest = () => ({
19522
19551
  {
19523
19552
  effects: [],
19524
19553
  path: "auth login",
19525
- summary: "Authorize this device through RSVP in your browser."
19554
+ summary: "Authorize this device through Registration in your browser."
19526
19555
  },
19527
19556
  {
19528
19557
  effects: [],
@@ -19537,12 +19566,12 @@ var getCommandManifest = () => ({
19537
19566
  {
19538
19567
  effects: [],
19539
19568
  path: "auth whoami",
19540
- summary: "Show the browser-authenticated RSVP identity."
19569
+ summary: "Show the browser-authenticated Registration identity."
19541
19570
  },
19542
19571
  {
19543
19572
  effects: [],
19544
19573
  path: "health",
19545
- summary: "Check the public RSVP API health endpoint."
19574
+ summary: "Check the public Registration API health endpoint."
19546
19575
  },
19547
19576
  {
19548
19577
  effects: [],
@@ -0,0 +1,38 @@
1
+ # Amgen D&D 2026: 9 September feedback
2
+
3
+ These files describe the reviewed changes and the applied test-event setup. **The corrected event details/deadline and dietary questions are active, and the 55-table venue layout was applied through Registration CLI (`rsvp`) on 10 September.** Remaining receipt/completion timing copy is saved as draft 22; active flow 11 is preserved to avoid invalidating existing participants' sessions and saved-answer display. See [applied configuration](applied-configuration.md) for exact state. No code was deployed and no participant emails were sent. The original full payloads retain older version/revision checks and must not be replayed unchanged.
4
+
5
+ - `event-setup.json`: revision-checked setup payload based on configuration version 7. Friday 27 November, 6:00–10:30pm; Simpor-Roselle Ballroom, Marina Bay Sands, Level 4. Registration closes **6 November 2026, 11:59pm Asia/Singapore**, confirmed by Noah. Event-specific entry label and deadline notice are presentation settings; existing editing permission checks remain intact.
6
+ - `flow-draft.json`: draft-save payload based on revision 20 and active published version 10. Adds participant-only dietary Yes/No and conditional required text on Response details (Step 3), enables summary details in completion/receipt, and supplies the requested later-QR timing copy. Existing menu version, consent version, authentication, guest rules, routing and other questions are preserved.
7
+ - `venue-layout.json`: 55 rounds × 10 seats, traced from the supplied MBS drawing. Tables 1 and 2 are VIP immediately in front of the stage centre, per Noah. All other tables are numbered sequentially from the top of the drawing. VIP labels do not introduce an access restriction. Room coordinates support screen navigation and are not surveyed dimensions.
8
+ - `sample-report.md`: clearly synthetic sample, with current export limitations identified.
9
+ - `verification.md`: per-item status, reproduced bugs, test evidence and staging boundaries.
10
+
11
+ ## Application and replay safety
12
+
13
+ Noah authorized test-event setup changes through Registration CLI (`rsvp`). The venue was applied with label/layout updates and table creation, preserving every original table/seat ID and booking; [applied venue](applied-venue.json) records the resulting IDs and geometry. The physical arrangement has **550 chairs** while the existing **500-person admission cap** remains unchanged.
14
+
15
+ Refresh the event, draft, resources and publication before further changes: stored versions are concurrency checks, not permission to overwrite newer work. Deploy compatible product code before using `publicPage` in the setup API. The current version-bound participant flow cannot safely activate even copy-only updates for existing registrations without re-admission and loss of their saved-answer display. Draft 22 therefore remains unpublished.
16
+
17
+ Deployment, QR release and scheduling/sending emails are still outside the authorized actions performed here.
18
+
19
+ The original PDF filename contains 2025, its title says 13 November 2026, and it is marked “DRAFTS ONLY SUBJECT TO APPROVAL”. Use the requested **27 November 2026** event date; the drawing provides the arrangement, not an event-date override.
20
+
21
+ ## QR delivery and activation
22
+
23
+ The exact attending copy is: “Check-in QR codes will be sent to your email address by 13Nov2026.” It distinguishes the immediate registration receipt from later check-in communication. This copy is a promised operational action, **not an implemented dispatch schedule**.
24
+
25
+ Initial read-only campaign inspection returned no campaigns for this test event. It has no explicit QR release policy; configured flows therefore keep QR tokens hidden. The scheduled-release feature makes codes visible on the confirmation page; it does not queue an email. The local code now supports a separate scheduled campaign with `{{checkInQrCodes}}`, producing labelled participant/guest PNG attachments with release and retry checks. Deploy and stage-check that code before scheduling it. Immediate receipts remain separate. The timing copy is saved in unpublished draft 22. No QR policy or campaign has been changed here; dispatch still needs a release/send timestamp and sending authorization.
26
+
27
+ ## Dashboard and access
28
+
29
+ - [Event admin dashboard](https://rsvp.getout.events/amgen/events/cmthccwii000501lgluebz2v2)
30
+ - [Reports](https://rsvp.getout.events/amgen/events/cmthccwii000501lgluebz2v2/reports)
31
+
32
+ The organization slug and event ID were verified through the authenticated Registration CLI (`rsvp`); the dashboard route was verified in an isolated browser to redirect anonymous users to sign-in while retaining the destination. Normal account email OTP and authorized organization membership/event assignment are required. Participant OTP/session access does not grant organizer access. Organization admins have full event/report access. Event admins/reporters require the corresponding report/export permissions, and identity, contact, employee ID and dietary information are separately protected by sensitive-data grants. CLI access itself requires global administrator status.
33
+
34
+ ## Source and inspection
35
+
36
+ Claudia Khng's feedback: Gmail account noah@getout.sg, thread `19fdba1fa00be9ef`, message `1a0866a32c63c3db`, 9 September 2026. Read with `gog --readonly --gmail-no-send`; quoted 4 September reply confirms retaining OTP. Screenshots `image001`, `image004`, `image005`, `image007` and the supplied single-page PDF were visually inspected.
37
+
38
+ Live configuration read on 9 September: 5–10pm, venue TBC, close 13 November 11:59pm, five sample tables, participant details disabled in receipt/completion, employee-ID email OTP active. Legacy setup has controlled-link access and no seating, but the active V2 publication governs participant admission and seating; this package preserves those unrelated legacy fields.
@@ -0,0 +1,54 @@
1
+ # Applied test-event configuration
2
+
3
+ Applied with Registration CLI (`rsvp`) after Noah authorized the event-information and dietary-flow updates in response annotations on 9 September 2026.
4
+
5
+ - Event: `cmthccwii000501lgluebz2v2`, `amgen-dinner-and-dance-2026-test`.
6
+ - Configuration version: **7 → 8**.
7
+ - Event starts **27 November 2026 at 6:00pm Singapore time** and ends **10:30pm**.
8
+ - Venue: **Simpor-Roselle Ballroom, Marina Bay Sands, Level 4**.
9
+ - Registration closes **6 November 2026 at 11:59pm Singapore time**.
10
+ - Description: “Review the event details and register by Fri, 06 Nov 2026”.
11
+ - Other setup values, including the 500-person admission cap, guest policy, editing checks and existing theme, were preserved.
12
+
13
+ The latest draft was identical to the active version before editing. The live preview validated the precise change without issues. Draft **20 → 21** was saved and published as active flow **11**, ID `cmtu9h6nn000301nint8op3bk`, at `2026-09-09T15:36:41.459Z` (11:36pm Singapore time).
14
+
15
+ Flow version 11 adds these participant-only custom fields on Step 3, Response details:
16
+
17
+ - “Do you have any dietary restrictions?” — required Yes/No when attending.
18
+ - “Please describe your dietary restrictions” — required text only when the previous answer is Yes.
19
+
20
+ Response details are enabled for completion/review and future participant registration receipts. Existing authentication, menus, guest questions, routing, consent, seating resources and receipt timing/body copy were preserved. No guest dietary question was added.
21
+
22
+ Read-back verification confirmed the public event values, exact saved definition, active version 11, draft revision 21, response-detail setting and employee-ID email OTP mode. Saving and publishing the flow did not send emails.
23
+
24
+ ## 10 September: venue applied, remaining flow copy saved
25
+
26
+ Noah authorized continuing the code fixes and test-event setup through Registration CLI (`rsvp`).
27
+ The new CLI seating commands were regression-tested locally, then used against
28
+ this test event's existing published map `cmthccwkf000g01lg5y6z343r`.
29
+
30
+ - Applied the supplied arrangement: **55 tables, 10 chairs each**.
31
+ - Tables **1 and 2 are VIP** immediately in front of the stage; the rest are numbered through 55.
32
+ - Moved and relabelled the five original tables, then created only the 50 additional tables.
33
+ - Read-back verified all **50 original seat IDs**, their exact booking records, and the **26 booking records** counted before and after. No reservations were released.
34
+ - Verified every table's coordinates, rotation, shape and capacity, plus the stage, screens, entrance and show-control geometry.
35
+ - Kept the **500-person admission cap**, configuration version **8**, and QR release **HIDDEN**.
36
+
37
+ The sanitized result is in [applied venue](applied-venue.json). Private before/after
38
+ snapshots and the CLI application journal stay outside Git in the local temporary
39
+ directory. No participant roster or names are included in this evidence.
40
+
41
+ The remaining attending receipt/completion copy was validated without issues and
42
+ saved as draft **21 → 22**, including the exact sentence “Check-in QR codes will be
43
+ sent to your email address by 13Nov2026.” **It was not published.** Active flow
44
+ **11** remains unchanged. Current publication changes bind admission sessions and
45
+ saved answers to a new version; publishing copy now would make existing participants
46
+ sign in again and present an empty form after admission. A safe version-compatible
47
+ publication design is needed before activating another version for these registrants.
48
+
49
+ ## Remaining activation boundaries
50
+
51
+ - OTP/session, validation/highlighting, seat-state, receipts and UI/branding code require deployment and staging integration verification.
52
+ - The entry CTA “Click here to register” and removal of the deadline/update sentence require the compatible local API/web changes. The deployed setup API does not accept the new `publicPage` fields; no unsupported update was attempted.
53
+ - Later QR-email campaign support is implemented and tested locally, with current-recipient, release and retry guards. QR delivery is a separate operation from visibility release. No campaign was scheduled or sent and no QR release policy was changed. The QR send time is still unspecified; 6 November 11:59pm is the registration cutoff, not a QR dispatch time.
54
+ - Full prepared `event-setup.json` and `flow-draft.json` remain original review artifacts with older concurrency versions. Do not replay them unchanged.