@go-labs-sg/rsvp 1.7.0 → 1.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.
Files changed (3) hide show
  1. package/README.md +86 -0
  2. package/dist/index.js +66 -2
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -85,6 +85,30 @@ The installed command uses the same portable Bun launcher as the other Go Labs C
85
85
 
86
86
  Global administrators can update another account's global role from the web user manager or with `rsvp user role update --allow-state-change --target <user-id> --payload '{"userId":"<user-id>","role":"admin"}'`. Administrators cannot remove their own global admin role.
87
87
 
88
+ ## Participant waitlist offers
89
+
90
+ ```sh
91
+ rsvp waitlist mine --ack-sensitive-data --payload '{"eventSlug":"event-slug","formSlug":"form-slug"}'
92
+ rsvp waitlist offer respond --allow-state-change --target 11111111-1111-4111-8111-111111111111 --payload '{"eventSlug":"event-slug","formSlug":"form-slug","action":"DECLINE","expectedRegistrationVersion":3,"idempotencyKey":"11111111-1111-4111-8111-111111111111"}'
93
+ ```
94
+
95
+ `formSlug` is optional. Both commands forward typed JSON to the shared participant
96
+ tRPC handlers; there is no CLI-specific selection or cancellation logic. `mine`
97
+ returns the unique active registration, or `registration: null` when only history
98
+ remains, with the existing time-zone field. `offer respond` accepts `ACCEPT` or
99
+ `DECLINE` and retains its payment/registration ID/version/status JSON output.
100
+ Obtain the expected version from `mine` and generate a fresh UUID for a new action;
101
+ reuse the exact same payload/key only when retrying that action. Keep the existing
102
+ sensitive-data acknowledgement and state-change/target guards.
103
+
104
+ Decline closes the live offer and releases active ownership, credentials and
105
+ remaining reservations atomically, while preserving response/audit history. An
106
+ identical retry remains a read-only receipt replay even after cancellation or a
107
+ fresh registration; changed payloads using the same key conflict. Historical rows
108
+ are never used as a current offer. Registration-again recovery still requires the
109
+ existing organizer archive/unarchive policy, not automatic readmission or restore.
110
+ No command, payload schema, effect guard, provider action or data repair is added.
111
+
88
112
  ## Personal seating drafts
89
113
 
90
114
  `event seating draft get`, `save`, `preview`, and `publish` use the same server-owned
@@ -776,6 +800,50 @@ population. Non-operational statuses remain excluded, and permissions, payment
776
800
  gates, duplicate protection, and undo behavior are unchanged. The web panel's
777
801
  realtime connection and manual refresh controls do not add a CLI subscription.
778
802
 
803
+ ### GOSH teams from check-in
804
+
805
+ A registration form can create a GOSH team and route the first time anyone
806
+ from the registration checks in. The first email is the registrant (captain);
807
+ the rest come from each attendee's email answer, in attendee order. RSVP saves
808
+ the request with the check-in and the worker sends it to GOSH afterwards, so
809
+ check-in never waits on GOSH. The crew screen shows **Pending team
810
+ assignment**, then the route and team name, or a failure to follow up.
811
+
812
+ The binding is off by default. Set it up in GOSH first (`gosh rsvp-check-in
813
+ binding set`), then link the RSVP form to the GOSH binding ID:
814
+
815
+ ```sh
816
+ rsvp check-in gosh binding set \
817
+ --allow-state-change \
818
+ --target form_123 \
819
+ --payload '{"organizationId":"org_123","eventId":"evt_123","flowId":"form_123","goshBindingId":"gosh_binding_id","memberEmailOutputKey":"teammate_email","enabled":true}'
820
+ rsvp check-in gosh list --payload '{"organizationId":"org_123","eventId":"evt_123","filter":"DELIVERY_FAILED"}'
821
+ rsvp check-in gosh retry --allow-state-change --target reg_123 \
822
+ --payload '{"organizationId":"org_123","eventId":"evt_123","registrationId":"reg_123"}'
823
+ rsvp check-in gosh reconcile --allow-state-change --target evt_123 \
824
+ --payload '{"organizationId":"org_123","eventId":"evt_123","dryRun":false,"retryFailed":true}'
825
+ ```
826
+
827
+ The worker needs `RSVP_GOSH_API_URL`, `RSVP_GOSH_CHECK_IN_KEY_ID` and
828
+ `RSVP_GOSH_CHECK_IN_SECRET` (the same `whsec_` secret GOSH holds under that key
829
+ ID). Without them, deliveries fail with a configuration error instead of
830
+ retrying forever.
831
+
832
+ - Only the first check-in of a registration sends a team. Teammates checking in
833
+ later, or at the same moment, do not create another team.
834
+ - Undoing the last check-in keeps the GOSH team and route but flags it for
835
+ review. Checking in again reuses the same team.
836
+ - Retry and reconcile reuse the same delivery ID, so GOSH returns the team it
837
+ already created. Reconcile defaults to `dryRun: true` and never rescans QR
838
+ codes or moves teams.
839
+ - A registration without a registrant email is rejected with
840
+ `CAPTAIN_EMAIL_MISSING` instead of making a teammate captain. Add the email,
841
+ then retry.
842
+ - Turning the binding off stops queued deliveries too; they show `PAUSED` and
843
+ attendance is kept. To resume, turn it back on, then run reconcile with
844
+ `"dryRun": false, "retryFailed": true`. Check-ins made while it was off are
845
+ picked up by the same reconcile.
846
+
779
847
  Set `registrationMasterList.includeAttendanceSheets: true` with an approved
780
848
  `event setup step update` (`section: "REGISTRATION_RULES"`) to add response-based
781
849
  **Attending**, **Not attending** (explicit declines only), and **All** tabs,
@@ -1109,6 +1177,24 @@ Confirmation and seat-change emails send from the server default
1109
1177
  `rsvp event email sender-domains`. Invalid local parts, a missing half of the
1110
1178
  pair or an unverified domain are rejected.
1111
1179
 
1180
+ ### Pending check-in details
1181
+
1182
+ While the check-in QR release is pending (scheduled or hidden), confirmation
1183
+ and resent confirmation emails show a "Check-in details" section with the
1184
+ release message and each attendee's name and type. Set
1185
+ `"showPendingCheckInDetails": false` in `registrationEmail` to omit that section
1186
+ when the event's own email copy already explains when QR codes arrive. Omitting
1187
+ the key, or setting `true`, keeps the section. After release the email shows
1188
+ check-in details, reference codes and attached QR codes as usual, whatever the
1189
+ setting. Seat-change emails have no check-in section and are unaffected.
1190
+
1191
+ ```sh
1192
+ rsvp event setup step update \
1193
+ --allow-state-change \
1194
+ --target evt_123 \
1195
+ --payload '{"organizationId":"org_123","eventId":"evt_123","version":7,"section":"REGISTRATION_RULES","registrationEmail":{"layout":"GROUPED","showPendingCheckInDetails":false}}'
1196
+ ```
1197
+
1112
1198
  `registrationEmail` replaces the whole presentation object, so read the current
1113
1199
  event first and resend every key you want to keep. Reply-to and support email
1114
1200
  are unchanged. If a saved domain is later unverified in Resend, those emails
package/dist/index.js CHANGED
@@ -10130,7 +10130,8 @@ var registrationEmailPresentationSchema = strictObject({
10130
10130
  seatingDisclaimer: string2().trim().min(1).max(2000).optional(),
10131
10131
  useResubmissionFooter: boolean2().default(false),
10132
10132
  supportEmail: email2().optional(),
10133
- showLuckyDrawId: boolean2().optional()
10133
+ showLuckyDrawId: boolean2().optional(),
10134
+ showPendingCheckInDetails: boolean2().optional()
10134
10135
  }).superRefine((value, ctx) => {
10135
10136
  if (Boolean(value.senderLocalPart) !== Boolean(value.senderDomain))
10136
10137
  ctx.addIssue({
@@ -11134,6 +11135,33 @@ var requestExportInputSchema = eventScopeSchema3.extend({
11134
11135
  var getExportDownloadInputSchema = eventScopeSchema3.extend({
11135
11136
  exportJobId: string2().min(1)
11136
11137
  });
11138
+ // ../validators/src/gosh-check-in.ts
11139
+ var id = string2().trim().min(1).max(128);
11140
+ var upsertGoshCheckInBindingInputSchema = organizationEventByIdInputSchema.extend({
11141
+ enabled: boolean2(),
11142
+ flowId: id,
11143
+ goshBindingId: id,
11144
+ memberEmailOutputKey: string2().trim().min(1).max(120).nullable()
11145
+ });
11146
+ var getGoshCheckInStatusInputSchema = organizationEventByIdInputSchema.extend({ registrationId: id });
11147
+ var listGoshCheckInSyncsInputSchema = organizationEventByIdInputSchema.extend({
11148
+ cursor: id.optional(),
11149
+ filter: _enum([
11150
+ "ALL",
11151
+ "PENDING",
11152
+ "ASSIGNED",
11153
+ "REJECTED",
11154
+ "DELIVERY_FAILED",
11155
+ "PAUSED"
11156
+ ]).default("ALL"),
11157
+ limit: number2().int().min(1).max(100).default(50)
11158
+ });
11159
+ var retryGoshCheckInDeliveryInputSchema = organizationEventByIdInputSchema.extend({ registrationId: id });
11160
+ var reconcileGoshCheckInInputSchema = organizationEventByIdInputSchema.extend({
11161
+ dryRun: boolean2().default(true),
11162
+ limit: number2().int().min(1).max(500).default(200),
11163
+ retryFailed: boolean2().default(false)
11164
+ });
11137
11165
  // ../validators/src/workflow.ts
11138
11166
  var verifyRegistrationIdentityInputSchema = object({
11139
11167
  eventSlug: eventSlugSchema,
@@ -12273,6 +12301,42 @@ var commands = {
12273
12301
  payloadOnly: true,
12274
12302
  summary: "Check in by attendee reference (--payload JSON)."
12275
12303
  },
12304
+ "check-in gosh binding list": {
12305
+ effects: [],
12306
+ operation: (api, input) => api.event.getGoshCheckInBindings.query(input),
12307
+ payloadOnly: true,
12308
+ summary: "List GOSH check-in team bindings for an event (--payload JSON). Requires event.manage."
12309
+ },
12310
+ "check-in gosh binding set": {
12311
+ effects: ["state-change"],
12312
+ operation: (api, input) => api.event.upsertGoshCheckInBinding.mutate(input),
12313
+ payloadOnly: true,
12314
+ summary: "Create or update the GOSH check-in team binding for a registration form: {organizationId, eventId, flowId, goshBindingId, memberEmailOutputKey, enabled} (--payload JSON). Disabled by default. Signing keys live in the RSVP worker environment, never in the binding."
12315
+ },
12316
+ "check-in gosh status": {
12317
+ effects: [],
12318
+ operation: (api, input) => api.event.getGoshCheckInStatus.query(input),
12319
+ payloadOnly: true,
12320
+ summary: "Show a registration's GOSH team route: NOT_CONFIGURED, PENDING, ASSIGNED, REJECTED, DELIVERY_FAILED, PAUSED or UNASSIGNED (--payload JSON). No emails are returned."
12321
+ },
12322
+ "check-in gosh list": {
12323
+ effects: [],
12324
+ operation: (api, input) => api.event.listGoshCheckInSyncs.query(input),
12325
+ payloadOnly: true,
12326
+ summary: "List registrations synced to GOSH teams with revision and status; filter ALL, PENDING, ASSIGNED, REJECTED, DELIVERY_FAILED or PAUSED (--payload JSON)."
12327
+ },
12328
+ "check-in gosh retry": {
12329
+ effects: ["state-change"],
12330
+ operation: (api, input) => api.event.retryGoshCheckInDelivery.mutate(input),
12331
+ payloadOnly: true,
12332
+ summary: "Requeue a registration's latest GOSH team assignment with the same webhook ID, so GOSH returns the stored team rather than creating another (--payload JSON)."
12333
+ },
12334
+ "check-in gosh reconcile": {
12335
+ effects: ["state-change"],
12336
+ operation: (api, input) => api.event.reconcileGoshCheckIn.mutate(input),
12337
+ payloadOnly: true,
12338
+ summary: "Find checked-in registrations missing a GOSH team assignment and enqueue them; retryFailed also requeues failed deliveries. dryRun defaults to true (--payload JSON)."
12339
+ },
12276
12340
  "check-in manual": {
12277
12341
  effects: ["state-change"],
12278
12342
  operation: (api, input) => api.event.manualCheckIn.mutate(input),
@@ -12567,7 +12631,7 @@ Object.assign(commands, {
12567
12631
  "event mine list": payloadCommand((api, input) => api.event.listMyEvents.query(input), "List the caller's events (--payload JSON)."),
12568
12632
  "event reminder list": payloadCommand((api, input) => api.event.listReminderSegments.query(input), "List reminder segments (--payload JSON).", ["sensitive-data"]),
12569
12633
  "event rsvp submit": payloadCommand((api, input) => api.event.submitRsvp.mutate(input), "Submit the caller's registration (--payload JSON).", ["sensitive-data", "state-change"]),
12570
- "event setup step update": payloadCommand((api, input) => api.event.updateSetupStep.mutate(input), "Update one revision-checked event setup step (--payload JSON). REGISTRATION_RULES accepts registrationEmail presentation (including senderName and a senderLocalPart+senderDomain address on a verified Resend sending domain), registrationMasterList output-key ordering/omissions and includeAttendanceSheets, and seatChangeNotification automatic/includeTablemates/includeFloorPlanImage policy (tablemate names default off; floor-plan image defaults on); omitted settings are preserved.", ["state-change"]),
12634
+ "event setup step update": payloadCommand((api, input) => api.event.updateSetupStep.mutate(input), "Update one revision-checked event setup step (--payload JSON). REGISTRATION_RULES accepts registrationEmail presentation (including senderName, a senderLocalPart+senderDomain address on a verified Resend sending domain, and showPendingCheckInDetails: false to omit the confirmation email's Check-in details section until the check-in QR release; released QR emails are unaffected), registrationMasterList output-key ordering/omissions and includeAttendanceSheets, and seatChangeNotification automatic/includeTablemates/includeFloorPlanImage policy (tablemate names default off; floor-plan image defaults on); omitted settings are preserved.", ["state-change"]),
12571
12635
  "event page update": payloadCommand((api, input) => api.event.updateSetupStep.mutate({
12572
12636
  ...input,
12573
12637
  section: "DETAILS_PAGE"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@go-labs-sg/rsvp",
3
- "version": "1.7.0",
3
+ "version": "1.9.0",
4
4
  "description": "RSVP CLI for authorized event operations.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",