@go-labs-sg/gosh 1.2.0 → 1.3.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
@@ -246,9 +246,22 @@ and missions stay editable after play starts: each edit re-syncs every started
246
246
  team's saved progress in the same transaction. Played stations keep their
247
247
  progress and order, while unplayed stations follow the new route. An edit that
248
248
  would remove the station a team is in the middle of fails with a conflict and
249
- changes nothing. A started team's group assignment, team creation, play mode
250
- and progression settings stay locked. A group shares its ordered station route,
251
- while each team keeps independent progress through that route.
249
+ changes nothing. A started team's group assignment, play mode and progression
250
+ settings stay locked. A group shares its ordered station route, while each team
251
+ keeps independent progress through that route.
252
+
253
+ Late teams can join a live group-routed event. `team create` must then include
254
+ a `groupId`, so the team starts on that group's route behind its release gate
255
+ (a held or scheduled group stays closed to it). Restoring an archived team
256
+ while group routing is live works only if the team never played and still has
257
+ a group. Without group routing, team creation still locks once play starts.
258
+
259
+ ```bash
260
+ gosh team create \
261
+ --input '{"eventId":"event-id","name":"Walk-in team","groupId":"group-id"}' \
262
+ --target event-id \
263
+ --allow-state-change
264
+ ```
252
265
 
253
266
  Configure gameplay, then manage the event's routing groups and their complete
254
267
  station lists:
@@ -379,6 +392,44 @@ gosh submission review \
379
392
  --allow-state-change
380
393
  ```
381
394
 
395
+ ### RSVP check-in teams
396
+
397
+ An RSVP form can create a GOSH team on its first successful check-in. RSVP
398
+ signs the request; GOSH creates the team from the registration's emails (the
399
+ first email is the captain, the rest are members), picks the least-loaded
400
+ route group that still has room, and returns the route. This also works
401
+ while the event is live, so a newly checked-in team can start playing.
402
+
403
+ The binding is off by default. Set the signing secret in the GOSH environment
404
+ as `GOSH_RSVP_CHECK_IN_WEBHOOK_SECRETS=<keyId>:whsec_...` (comma separated
405
+ during rotation). The secret is never stored in the binding.
406
+
407
+ ```bash
408
+ gosh rsvp-check-in binding set \
409
+ --input '{"eventId":"event-id","sourceOrganizationId":"rsvp-org-id","sourceEventId":"rsvp-event-id","sourceFormId":"rsvp-form-id","keyId":"farm-2026","enabled":true,"groups":[{"groupId":"group-a","teamCapacity":125},{"groupId":"group-b","teamCapacity":125},{"groupId":"group-c","teamCapacity":125},{"groupId":"group-d","teamCapacity":125}],"totalTeamCapacity":500,"maxRosterSize":2}' \
410
+ --target event-id \
411
+ --allow-state-change
412
+ gosh rsvp-check-in binding get --input '{"eventId":"event-id"}'
413
+ gosh rsvp-check-in links list --input '{"eventId":"event-id","filter":"REVIEW"}'
414
+ ```
415
+
416
+ - Group load counts every non-archived team in the group, including teams
417
+ assigned by hand. While the binding is enabled, `routing-group assign-team`
418
+ and restoring an archived team are refused if they would exceed a group's
419
+ capacity or the total limit.
420
+ - Groups with equal load are filled in the order listed in `groups`.
421
+ - When every route is full, GOSH creates no team and RSVP shows
422
+ `CAPACITY_FULL`. The attendee stays checked in.
423
+ - Email addresses are matched case-insensitively. Repeated addresses are
424
+ counted once. An invalid address, a suspended account, a player removed
425
+ from the event, or a player already on another team rejects the whole
426
+ team, and nothing is created.
427
+ - New accounts are not marked verified, and GOSH sends no email. Players sign
428
+ in later with the normal email code.
429
+ - Undoing the last RSVP check-in keeps the team and route but flags the team
430
+ for review. Clear the flag with `gosh rsvp-check-in review resolve`. A later
431
+ check-in reuses the same team.
432
+
382
433
  ### Artwork requirements (no login required)
383
434
 
384
435
  Read the bundled upload policy before preparing station, mission, or branding artwork:
@@ -1239,9 +1239,47 @@
1239
1239
  "path": ["routing-group", "assign-team"],
1240
1240
  "procedure": "team.assignTeamRoutingGroup",
1241
1241
  "requiresAuth": true,
1242
- "summary": "Assign a team to a routing group, or clear its assignment with groupId null, before play starts.",
1242
+ "summary": "Assign a team to a routing group, or clear its assignment with groupId null, before play starts. Groups covered by an enabled RSVP check-in binding reject moves that exceed their team capacity.",
1243
1243
  "targetKeys": ["teamId"]
1244
1244
  },
1245
+ {
1246
+ "effects": [],
1247
+ "input": "json",
1248
+ "operation": "query",
1249
+ "path": ["rsvp-check-in", "binding", "get"],
1250
+ "procedure": "team.getRsvpCheckInBinding",
1251
+ "requiresAuth": true,
1252
+ "summary": "Show the RSVP check-in team binding for an event: source RSVP organization/event/form, key ID, enabled flag, ordered routing groups with team capacity and current load, total limit and roster size limit. Secrets are never stored or shown. Requires editSetup."
1253
+ },
1254
+ {
1255
+ "effects": ["state-change"],
1256
+ "input": "json",
1257
+ "operation": "mutation",
1258
+ "path": ["rsvp-check-in", "binding", "set"],
1259
+ "procedure": "team.upsertRsvpCheckInBinding",
1260
+ "requiresAuth": true,
1261
+ "summary": "Create or replace the RSVP check-in team binding: {eventId, sourceOrganizationId, sourceEventId, sourceFormId, keyId, enabled, groups:[{groupId, teamCapacity}] in tie-break order, totalTeamCapacity, maxRosterSize}. Disabled by default; the signing secret is set in the GOSH_RSVP_CHECK_IN_WEBHOOK_SECRETS environment variable under keyId. Requires launchEvent.",
1262
+ "targetKeys": ["eventId", "sourceFormId"]
1263
+ },
1264
+ {
1265
+ "effects": [],
1266
+ "input": "json",
1267
+ "operation": "query",
1268
+ "path": ["rsvp-check-in", "links", "list"],
1269
+ "procedure": "team.listRsvpCheckInLinks",
1270
+ "requiresAuth": true,
1271
+ "summary": "List RSVP registrations linked to check-in teams with route, applied revision, review flag and rejection code. filter ALL, REVIEW (undone check-ins) or REJECTED. Requires editSetup."
1272
+ },
1273
+ {
1274
+ "effects": ["state-change"],
1275
+ "input": "json",
1276
+ "operation": "mutation",
1277
+ "path": ["rsvp-check-in", "review", "resolve"],
1278
+ "procedure": "team.resolveRsvpCheckInReview",
1279
+ "requiresAuth": true,
1280
+ "summary": "Clear the review flag on an RSVP check-in team after crew follow-up. The team and its route are unchanged. Requires editSetup.",
1281
+ "targetKeys": ["linkId"]
1282
+ },
1245
1283
  {
1246
1284
  "effects": [],
1247
1285
  "input": "json",
@@ -1964,6 +2002,79 @@
1964
2002
  "name"
1965
2003
  ]
1966
2004
  },
2005
+ {
2006
+ "effects": ["state-change"],
2007
+ "input": "json",
2008
+ "operation": "mutation",
2009
+ "path": ["station", "update-check-in"],
2010
+ "procedure": "event.updateStationCheckIn",
2011
+ "requiresAuth": true,
2012
+ "summary": "Set how players unlock a station: open, location, QR, or both.",
2013
+ "targetKeys": [
2014
+ "id",
2015
+ "memberId",
2016
+ "invitationId",
2017
+ "broadcastId",
2018
+ "rewardId",
2019
+ "submissionId",
2020
+ "participantId",
2021
+ "participantIds",
2022
+ "missionId",
2023
+ "stationId",
2024
+ "teamId",
2025
+ "templateId",
2026
+ "eventId",
2027
+ "organizationId",
2028
+ "userId",
2029
+ "key",
2030
+ "uploadId",
2031
+ "email",
2032
+ "joinCode",
2033
+ "slug",
2034
+ "name"
2035
+ ]
2036
+ },
2037
+ {
2038
+ "effects": [],
2039
+ "input": "json",
2040
+ "operation": "query",
2041
+ "path": ["station", "qr-codes"],
2042
+ "procedure": "event.getStationQrCodes",
2043
+ "requiresAuth": true,
2044
+ "summary": "List printable QR codes and manual codes for QR-enabled stations."
2045
+ },
2046
+ {
2047
+ "effects": ["state-change"],
2048
+ "input": "json",
2049
+ "operation": "mutation",
2050
+ "path": ["station", "regenerate-qr"],
2051
+ "procedure": "event.regenerateStationQr",
2052
+ "requiresAuth": true,
2053
+ "summary": "Regenerate a station QR. Earlier prints stop working.",
2054
+ "targetKeys": [
2055
+ "id",
2056
+ "memberId",
2057
+ "invitationId",
2058
+ "broadcastId",
2059
+ "rewardId",
2060
+ "submissionId",
2061
+ "participantId",
2062
+ "participantIds",
2063
+ "missionId",
2064
+ "stationId",
2065
+ "teamId",
2066
+ "templateId",
2067
+ "eventId",
2068
+ "organizationId",
2069
+ "userId",
2070
+ "key",
2071
+ "uploadId",
2072
+ "email",
2073
+ "joinCode",
2074
+ "slug",
2075
+ "name"
2076
+ ]
2077
+ },
1967
2078
  {
1968
2079
  "effects": ["state-change"],
1969
2080
  "input": "json",
@@ -2288,6 +2399,38 @@
2288
2399
  "name"
2289
2400
  ]
2290
2401
  },
2402
+ {
2403
+ "effects": ["state-change"],
2404
+ "input": "json",
2405
+ "operation": "mutation",
2406
+ "path": ["player", "station-qr-check-in"],
2407
+ "procedure": "event.createStationQrCheckInProof",
2408
+ "requiresAuth": true,
2409
+ "summary": "Check in to a station with its scanned QR or manual code.",
2410
+ "targetKeys": [
2411
+ "id",
2412
+ "memberId",
2413
+ "invitationId",
2414
+ "broadcastId",
2415
+ "rewardId",
2416
+ "submissionId",
2417
+ "participantId",
2418
+ "participantIds",
2419
+ "missionId",
2420
+ "stationId",
2421
+ "teamId",
2422
+ "templateId",
2423
+ "eventId",
2424
+ "organizationId",
2425
+ "userId",
2426
+ "key",
2427
+ "uploadId",
2428
+ "email",
2429
+ "joinCode",
2430
+ "slug",
2431
+ "name"
2432
+ ]
2433
+ },
2291
2434
  {
2292
2435
  "effects": ["state-change"],
2293
2436
  "input": "json",
@@ -500,7 +500,39 @@ Replace a group's complete station route in the supplied order before play start
500
500
 
501
501
  ## `gosh routing-group assign-team`
502
502
 
503
- Assign a team to a routing group, or clear its assignment with groupId null, before play starts.
503
+ Assign a team to a routing group, or clear its assignment with groupId null, before play starts. Groups covered by an enabled RSVP check-in binding reject moves that exceed their team capacity.
504
+
505
+ - Authentication: browser-authenticated CLI session required
506
+ - Input: `--input '<json>'` required
507
+ - Effects: state-change
508
+
509
+ ## `gosh rsvp-check-in binding get`
510
+
511
+ Show the RSVP check-in team binding for an event: source RSVP organization/event/form, key ID, enabled flag, ordered routing groups with team capacity and current load, total limit and roster size limit. Secrets are never stored or shown. Requires editSetup.
512
+
513
+ - Authentication: browser-authenticated CLI session required
514
+ - Input: `--input '<json>'` required
515
+ - Effects: read-only
516
+
517
+ ## `gosh rsvp-check-in binding set`
518
+
519
+ Create or replace the RSVP check-in team binding: {eventId, sourceOrganizationId, sourceEventId, sourceFormId, keyId, enabled, groups:[{groupId, teamCapacity}] in tie-break order, totalTeamCapacity, maxRosterSize}. Disabled by default; the signing secret is set in the GOSH_RSVP_CHECK_IN_WEBHOOK_SECRETS environment variable under keyId. Requires launchEvent.
520
+
521
+ - Authentication: browser-authenticated CLI session required
522
+ - Input: `--input '<json>'` required
523
+ - Effects: state-change
524
+
525
+ ## `gosh rsvp-check-in links list`
526
+
527
+ List RSVP registrations linked to check-in teams with route, applied revision, review flag and rejection code. filter ALL, REVIEW (undone check-ins) or REJECTED. Requires editSetup.
528
+
529
+ - Authentication: browser-authenticated CLI session required
530
+ - Input: `--input '<json>'` required
531
+ - Effects: read-only
532
+
533
+ ## `gosh rsvp-check-in review resolve`
534
+
535
+ Clear the review flag on an RSVP check-in team after crew follow-up. The team and its route are unchanged. Requires editSetup.
504
536
 
505
537
  - Authentication: browser-authenticated CLI session required
506
538
  - Input: `--input '<json>'` required
@@ -778,6 +810,30 @@ Update station location and geofence settings.
778
810
  - Input: `--input '<json>'` required
779
811
  - Effects: state-change
780
812
 
813
+ ## `gosh station update-check-in`
814
+
815
+ Set how players unlock a station: open, location, QR, or both.
816
+
817
+ - Authentication: browser-authenticated CLI session required
818
+ - Input: `--input '<json>'` required
819
+ - Effects: state-change
820
+
821
+ ## `gosh station qr-codes`
822
+
823
+ List printable QR codes and manual codes for QR-enabled stations.
824
+
825
+ - Authentication: browser-authenticated CLI session required
826
+ - Input: `--input '<json>'` required
827
+ - Effects: read-only
828
+
829
+ ## `gosh station regenerate-qr`
830
+
831
+ Regenerate a station QR. Earlier prints stop working.
832
+
833
+ - Authentication: browser-authenticated CLI session required
834
+ - Input: `--input '<json>'` required
835
+ - Effects: state-change
836
+
781
837
  ## `gosh event save-as-template`
782
838
 
783
839
  Save an event as a template.
@@ -922,6 +978,14 @@ Create an expiring station check-in proof.
922
978
  - Input: `--input '<json>'` required
923
979
  - Effects: state-change
924
980
 
981
+ ## `gosh player station-qr-check-in`
982
+
983
+ Check in to a station with its scanned QR or manual code.
984
+
985
+ - Authentication: browser-authenticated CLI session required
986
+ - Input: `--input '<json>'` required
987
+ - Effects: state-change
988
+
925
989
  ## `gosh player station start`
926
990
 
927
991
  Start the current sequential station's shared mission timer and reveal its missions; required check-in still applies.
package/dist/index.js CHANGED
@@ -7520,6 +7520,22 @@ var typedOperations = {
7520
7520
  kind: "mutation",
7521
7521
  invoke: (client, input) => client.team.assignTeamRoutingGroup.mutate(input)
7522
7522
  },
7523
+ "team.getRsvpCheckInBinding": {
7524
+ kind: "query",
7525
+ invoke: (client, input) => client.team.getRsvpCheckInBinding.query(input)
7526
+ },
7527
+ "team.upsertRsvpCheckInBinding": {
7528
+ kind: "mutation",
7529
+ invoke: (client, input) => client.team.upsertRsvpCheckInBinding.mutate(input)
7530
+ },
7531
+ "team.listRsvpCheckInLinks": {
7532
+ kind: "query",
7533
+ invoke: (client, input) => client.team.listRsvpCheckInLinks.query(input)
7534
+ },
7535
+ "team.resolveRsvpCheckInReview": {
7536
+ kind: "mutation",
7537
+ invoke: (client, input) => client.team.resolveRsvpCheckInReview.mutate(input)
7538
+ },
7523
7539
  "template.list": {
7524
7540
  kind: "query",
7525
7541
  invoke: (client, input) => client.template.list.query(input)
@@ -7656,6 +7672,18 @@ var typedOperations = {
7656
7672
  kind: "mutation",
7657
7673
  invoke: (client, input) => client.event.updateStationLocation.mutate(input)
7658
7674
  },
7675
+ "event.updateStationCheckIn": {
7676
+ kind: "mutation",
7677
+ invoke: (client, input) => client.event.updateStationCheckIn.mutate(input)
7678
+ },
7679
+ "event.getStationQrCodes": {
7680
+ kind: "query",
7681
+ invoke: (client, input) => client.event.getStationQrCodes.query(input)
7682
+ },
7683
+ "event.regenerateStationQr": {
7684
+ kind: "mutation",
7685
+ invoke: (client, input) => client.event.regenerateStationQr.mutate(input)
7686
+ },
7659
7687
  "event.saveAsTemplate": {
7660
7688
  kind: "mutation",
7661
7689
  invoke: (client, input) => client.event.saveAsTemplate.mutate(input)
@@ -7728,6 +7756,10 @@ var typedOperations = {
7728
7756
  kind: "mutation",
7729
7757
  invoke: (client, input) => client.event.createStationCheckInProof.mutate(input)
7730
7758
  },
7759
+ "event.createStationQrCheckInProof": {
7760
+ kind: "mutation",
7761
+ invoke: (client, input) => client.event.createStationQrCheckInProof.mutate(input)
7762
+ },
7731
7763
  "event.startStation": {
7732
7764
  kind: "mutation",
7733
7765
  invoke: (client, input) => client.event.startStation.mutate(input)
@@ -7923,6 +7955,8 @@ var mutationTargetKeys = {
7923
7955
  "team.deleteRoutingGroup": ["groupId"],
7924
7956
  "team.setRoutingGroupStations": ["groupId"],
7925
7957
  "team.assignTeamRoutingGroup": ["teamId"],
7958
+ "team.upsertRsvpCheckInBinding": ["eventId", "sourceFormId"],
7959
+ "team.resolveRsvpCheckInReview": ["linkId"],
7926
7960
  "event.startStation": ["stationId"],
7927
7961
  "event.skipMission": ["missionId"],
7928
7962
  "event.reopenMission": ["teamId", "eventPlayerId", "missionId"],
@@ -8042,7 +8076,11 @@ var commands = [
8042
8076
  mutation(["routing-group", "rename"], "team.renameRoutingGroup", "Rename an event's routing group before play starts.", ["state-change"]),
8043
8077
  mutation(["routing-group", "delete"], "team.deleteRoutingGroup", "Delete an unassigned routing group before play starts.", ["state-change", "delete"]),
8044
8078
  mutation(["routing-group", "set-stations"], "team.setRoutingGroupStations", "Replace a group's complete station route in the supplied order before play starts.", ["state-change"]),
8045
- mutation(["routing-group", "assign-team"], "team.assignTeamRoutingGroup", "Assign a team to a routing group, or clear its assignment with groupId null, before play starts.", ["state-change"]),
8079
+ mutation(["routing-group", "assign-team"], "team.assignTeamRoutingGroup", "Assign a team to a routing group, or clear its assignment with groupId null, before play starts. Groups covered by an enabled RSVP check-in binding reject moves that exceed their team capacity.", ["state-change"]),
8080
+ query(["rsvp-check-in", "binding", "get"], "team.getRsvpCheckInBinding", "Show the RSVP check-in team binding for an event: source RSVP organization/event/form, key ID, enabled flag, ordered routing groups with team capacity and current load, total limit and roster size limit. Secrets are never stored or shown. Requires editSetup."),
8081
+ mutation(["rsvp-check-in", "binding", "set"], "team.upsertRsvpCheckInBinding", "Create or replace the RSVP check-in team binding: {eventId, sourceOrganizationId, sourceEventId, sourceFormId, keyId, enabled, groups:[{groupId, teamCapacity}] in tie-break order, totalTeamCapacity, maxRosterSize}. Disabled by default; the signing secret is set in the GOSH_RSVP_CHECK_IN_WEBHOOK_SECRETS environment variable under keyId. Requires launchEvent.", ["state-change"]),
8082
+ query(["rsvp-check-in", "links", "list"], "team.listRsvpCheckInLinks", "List RSVP registrations linked to check-in teams with route, applied revision, review flag and rejection code. filter ALL, REVIEW (undone check-ins) or REJECTED. Requires editSetup."),
8083
+ mutation(["rsvp-check-in", "review", "resolve"], "team.resolveRsvpCheckInReview", "Clear the review flag on an RSVP check-in team after crew follow-up. The team and its route are unchanged. Requires editSetup.", ["state-change"]),
8046
8084
  query(["template", "list"], "template.list", "List templates visible in an organization; global admins can include every organization."),
8047
8085
  query(["template", "get"], "template.getById", "Get a template visible in the requested organization; global admins can get any template."),
8048
8086
  mutation(["template", "create"], "template.create", "Create an organization template, including shared stations with optional per-team route order.", ["state-change"]),
@@ -8080,6 +8118,9 @@ var commands = [
8080
8118
  mutation(["station", "update-availability"], "event.updateStationAvailability", "Update station availability.", ["state-change"]),
8081
8119
  mutation(["station", "update-image"], "event.updateStationImage", "Update a station image.", ["state-change"]),
8082
8120
  mutation(["station", "update-location"], "event.updateStationLocation", "Update station location and geofence settings.", ["state-change"]),
8121
+ mutation(["station", "update-check-in"], "event.updateStationCheckIn", "Set how players unlock a station: open, location, QR, or both.", ["state-change"]),
8122
+ query(["station", "qr-codes"], "event.getStationQrCodes", "List printable QR codes and manual codes for QR-enabled stations."),
8123
+ mutation(["station", "regenerate-qr"], "event.regenerateStationQr", "Regenerate a station QR. Earlier prints stop working.", ["state-change"]),
8083
8124
  mutation(["event", "save-as-template"], "event.saveAsTemplate", "Save an event as a template.", ["state-change"]),
8084
8125
  query(["player", "event"], "event.getJoinDetails", "Get the current player's event details."),
8085
8126
  query(["player", "leaderboard", "page"], "event.getPaginatedPlayerLeaderboard", "Get a page of the player leaderboard."),
@@ -8100,6 +8141,7 @@ var commands = [
8100
8141
  mutation(["player", "display-name", "update"], "event.updatePlayerDisplayName", "Update the player's display name.", ["state-change"]),
8101
8142
  mutation(["player", "resolve-join-code"], "event.resolveJoinCode", "Resolve an event or team join code.", []),
8102
8143
  mutation(["player", "station-check-in"], "event.createStationCheckInProof", "Create an expiring station check-in proof.", ["state-change"]),
8144
+ mutation(["player", "station-qr-check-in"], "event.createStationQrCheckInProof", "Check in to a station with its scanned QR or manual code.", ["state-change"]),
8103
8145
  mutation(["player", "station", "start"], "event.startStation", "Start the current sequential station's shared mission timer and reveal its missions; required check-in still applies.", ["state-change"]),
8104
8146
  mutation(["player", "mission", "skip"], "event.skipMission", "Permanently skip one unresolved mission for zero points when enabled; retain other points and elapsed station time.", ["state-change"]),
8105
8147
  mutation(["player", "mission", "submit"], "event.submitMission", "Submit a mission response and return revealMessage, including already-completed submissions.", ["state-change"]),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@go-labs-sg/gosh",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "GOSH CLI for organizers and AI agents — manage organizations, events, teams, stations, missions, templates, and live operations through the GOSH API.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",