@jsm-mit/sultana-core-motoko-package 0.2.0 → 0.4.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.
@@ -75,6 +75,16 @@ type UpdateSalonServiceArgs =
75
75
  serviceTypeIds: vec ServiceTypeId;
76
76
  workerIds: vec principal;
77
77
  };
78
+ type UpdatePromoArgs =
79
+ record {
80
+ assetId: AssetId;
81
+ chips: vec text;
82
+ cta: PromoCta;
83
+ promoId: PromoId;
84
+ salonId: SalonId;
85
+ target: PromoTarget;
86
+ textLines: vec text;
87
+ };
78
88
  type UpdateProfileArgs =
79
89
  record {
80
90
  avatarUrl: opt text;
@@ -127,6 +137,12 @@ type SetReportThresholdArgs =
127
137
  opType: OperationType;
128
138
  thresholdMs: nat;
129
139
  };
140
+ type SetPromoActiveArgs =
141
+ record {
142
+ active: bool;
143
+ promoId: PromoId;
144
+ salonId: SalonId;
145
+ };
130
146
  type SetLanguageActiveArgs =
131
147
  record {
132
148
  active: bool;
@@ -195,6 +211,11 @@ type SalonPublicInfo =
195
211
  name: text;
196
212
  thumbnailAssetId: opt AssetId;
197
213
  };
214
+ type SalonInvite =
215
+ record {
216
+ expiresAtNs: int;
217
+ token: text;
218
+ };
198
219
  type SalonId = text;
199
220
  type SalonCandidatesEntry =
200
221
  record {
@@ -264,47 +285,52 @@ type Result_4 =
264
285
  err: Error;
265
286
  ok: principal;
266
287
  };
267
- type Result_35 =
288
+ type Result_37 =
268
289
  variant {
269
290
  err: Error;
270
291
  ok: PromoId;
271
292
  };
272
- type Result_34 =
293
+ type Result_36 =
273
294
  variant {
274
295
  err: Error;
275
296
  ok: SalonServiceId;
276
297
  };
277
- type Result_33 =
298
+ type Result_35 =
278
299
  variant {
279
300
  err: Error;
280
301
  ok: vec SalonServiceId;
281
302
  };
282
- type Result_32 =
303
+ type Result_34 =
283
304
  variant {
284
305
  err: Error;
285
306
  ok: vec SalonId;
286
307
  };
287
- type Result_31 =
308
+ type Result_33 =
288
309
  variant {
289
310
  err: Error;
290
311
  ok: AppointmentId;
291
312
  };
292
- type Result_30 =
313
+ type Result_32 =
293
314
  variant {
294
315
  err: Error;
295
- ok: ActionQuotaLimits;
316
+ ok: SalonInvite;
296
317
  };
297
- type Result_3 =
318
+ type Result_31 =
298
319
  variant {
299
320
  err: Error;
300
- ok: nat;
321
+ ok: ActionQuotaLimits;
301
322
  };
302
- type Result_29 =
323
+ type Result_30 =
303
324
  variant {
304
325
  err: Error;
305
326
  ok: vec SupportedLanguage;
306
327
  };
307
- type Result_28 =
328
+ type Result_3 =
329
+ variant {
330
+ err: Error;
331
+ ok: nat;
332
+ };
333
+ type Result_29 =
308
334
  variant {
309
335
  err: Error;
310
336
  ok: record {
@@ -312,32 +338,32 @@ type Result_28 =
312
338
  trackingSinceNs: nat64;
313
339
  };
314
340
  };
315
- type Result_27 =
341
+ type Result_28 =
316
342
  variant {
317
343
  err: Error;
318
344
  ok: vec DailyScheduleEntry;
319
345
  };
320
- type Result_26 =
346
+ type Result_27 =
321
347
  variant {
322
348
  err: Error;
323
349
  ok: vec nat64;
324
350
  };
325
- type Result_25 =
351
+ type Result_26 =
326
352
  variant {
327
353
  err: Error;
328
354
  ok: TimeMask;
329
355
  };
330
- type Result_24 =
356
+ type Result_25 =
331
357
  variant {
332
358
  err: Error;
333
359
  ok: MigrationData;
334
360
  };
335
- type Result_23 =
361
+ type Result_24 =
336
362
  variant {
337
363
  err: Error;
338
364
  ok: vec Appointment;
339
365
  };
340
- type Result_22 =
366
+ type Result_23 =
341
367
  variant {
342
368
  err: Error;
343
369
  ok: record {
@@ -346,16 +372,21 @@ type Result_22 =
346
372
  updateThresholdMs: nat;
347
373
  };
348
374
  };
349
- type Result_21 =
375
+ type Result_22 =
350
376
  variant {
351
377
  err: Error;
352
378
  ok: vec SalonAsset;
353
379
  };
354
- type Result_20 =
380
+ type Result_21 =
355
381
  variant {
356
382
  err: Error;
357
383
  ok: vec DiscountCode;
358
384
  };
385
+ type Result_20 =
386
+ variant {
387
+ err: Error;
388
+ ok: opt SalonInvite;
389
+ };
359
390
  type Result_2 =
360
391
  variant {
361
392
  err: Error;
@@ -421,7 +452,11 @@ type Result =
421
452
  err: Error;
422
453
  ok: VisitId;
423
454
  };
424
- type RequestToJoinArgs = record {salonId: SalonId;};
455
+ type RequestToJoinArgs =
456
+ record {
457
+ salonId: SalonId;
458
+ token: text;
459
+ };
425
460
  type RemoveWorkerFromSalonArgs =
426
461
  record {
427
462
  salonId: SalonId;
@@ -478,6 +513,7 @@ type PromoTarget =
478
513
  };
479
514
  type PromoItem =
480
515
  record {
516
+ active: bool;
481
517
  assetId: AssetId;
482
518
  chips: vec text;
483
519
  createdAt: int;
@@ -683,6 +719,11 @@ type Coordinate =
683
719
  lat: float64;
684
720
  lng: float64;
685
721
  };
722
+ type CheckSalonInviteArgs =
723
+ record {
724
+ salonId: SalonId;
725
+ token: text;
726
+ };
686
727
  type CanUploadAssetArgs =
687
728
  record {
688
729
  declaredSizeBytes: opt nat;
@@ -832,32 +873,38 @@ service : {
832
873
  addDiscountCode: (args: AddDiscountCodeArgs) -> (Result_1);
833
874
  /// Superadmin: adds a supported language (active by default; languages are never deleted)
834
875
  addLanguage: (code: LangCode) -> (Result_1);
835
- /// Owner attaches a promo (max 3 per salon): #Ready media from the salon's library,
836
- /// target = the salon or one of its services, CTA = button label / show-delay / discount code
837
- addPromo: (args: AddPromoArgs) -> (Result_35);
876
+ /// Owner adds a promo to the salon's library (max 15): #Ready media from the salon's
877
+ /// library, target = the salon or one of its services, CTA = button label / discount code.
878
+ /// The promo is created INACTIVE — setPromoActive is what puts it in the feed
879
+ addPromo: (args: AddPromoArgs) -> (Result_37);
838
880
  /// Adds a new service to a specific salon
839
- addSalonService: (args: AddSalonServiceArgs) -> (Result_34);
881
+ addSalonService: (args: AddSalonServiceArgs) -> (Result_36);
840
882
  addServiceType: (id: ServiceTypeId) -> (Result_1);
841
883
  addServiceTypeToSalonService: (args: AddOrRemoveServiceTypeInSalonArgs) ->
842
884
  (Result_1);
843
885
  addWorkerToSalonService: (args: AddOrRemoveWorkerInSalonArgs) -> (Result_1);
844
886
  /// Owner attaches an image from the salon's library to one of that salon's services
845
887
  attachImageToSalonService: (args: AttachOrDetachImageArgs) -> (Result_1);
846
- bookAppointment: (args: BookAppointmentArgs) -> (Result_31);
888
+ bookAppointment: (args: BookAppointmentArgs) -> (Result_33);
847
889
  bulkAcceptWorkers: (args: BulkAcceptWorkersArgs) -> (Result_1);
848
- bulkAddSalonServices: (args: BulkAddSalonServicesArgs) -> (Result_33);
890
+ bulkAddSalonServices: (args: BulkAddSalonServicesArgs) -> (Result_35);
849
891
  bulkAddServiceTypes: (ids: vec ServiceTypeId) -> (Result_14);
850
- bulkCreateSalons: (args: BulkCreateSalonsArgs) -> (Result_32);
892
+ bulkCreateSalons: (args: BulkCreateSalonsArgs) -> (Result_34);
851
893
  bulkRequestToJoinSalons: (args: BulkRequestToJoinSalonsArgs) -> (Result_1);
852
894
  /// Superadmin: bulk import of translations (seeding / migration) — all-or-nothing batch
853
895
  bulkSetTranslations: (items: vec SetTranslationArgs) -> (Result_3);
854
896
  bulkSetWeeklyTemplates: (args: BulkSetWeeklyTemplatesArgs) -> (Result_1);
855
897
  /// Asset canister only: pre-upload authorization, asked before any bytes are stored
856
898
  canUploadAsset: (args: CanUploadAssetArgs) -> (Result_1);
857
- cancelAppointment: (appointmentId: AppointmentId) -> (Result_31);
899
+ cancelAppointment: (appointmentId: AppointmentId) -> (Result_33);
900
+ /// Is an invite link still good? Open to anonymous callers — the page behind the link has
901
+ /// to answer before there is an identity to ask about.
902
+ checkSalonInvite: (args: CheckSalonInviteArgs) -> (Result_1) query;
858
903
  clearLogs: () -> ();
859
904
  /// Creates a new salon and links it to the caller
860
905
  createSalon: (args: CreateSalonArgs) -> (Result_5);
906
+ /// Owner mints the salon's worker-invite link (replaces any outstanding one)
907
+ createSalonInvite: (salonId: SalonId) -> (Result_32);
861
908
  createVisit: (args: CreateVisitArgs) -> (Result);
862
909
  /// Superadmin only: raw byte removal on sultana-assets-rust (orphaned-bytes cleanup)
863
910
  deleteAssetRaw: (assetId: text) -> (Result_1);
@@ -868,49 +915,52 @@ service : {
868
915
  deregisterAsset: (args: DeregisterAssetArgs) -> (Result_1);
869
916
  /// Owner detaches an image from a service (the asset stays in the salon's library)
870
917
  detachImageFromSalonService: (args: AttachOrDetachImageArgs) -> (Result_1);
871
- getActionQuotaLimits: () -> (Result_30) query;
918
+ getActionQuotaLimits: () -> (Result_31) query;
872
919
  /// Superadmin: every supported language incl. inactive ones (admin panel view)
873
- getAllLanguages: () -> (Result_29) query;
920
+ getAllLanguages: () -> (Result_30) query;
874
921
  getAllProfiles: () -> (Result_8) query;
875
922
  getAppointmentsForSalon: (args: GetSalonAppointmentsArgs) ->
876
- (Result_23) query;
923
+ (Result_24) query;
877
924
  getAssetCanisterPrincipal: () -> (Result_4) query;
878
925
  /// Superadmin-only: returns every principal's lifetime (total, productive) call counters plus the tracking window start
879
- getCallActivityStats: () -> (Result_28) query;
926
+ getCallActivityStats: () -> (Result_29) query;
880
927
  /// Returns the list of profiles waiting for approval (Owner only)
881
928
  getCandidatesBySalonId: (salonId: SalonId) -> (Result_8) query;
882
929
  /// Returns a specific daily override if it exists
883
- getDailySchedule: (args: GetDailyScheduleArgs) -> (Result_25) query;
930
+ getDailySchedule: (args: GetDailyScheduleArgs) -> (Result_26) query;
884
931
  /// Returns daily schedules with midnight timestamp in [fromDate, toDate] - for data migration to another canister
885
932
  getDailySchedulesForMigration: (args: DailyScheduleRangeArgs) ->
886
- (Result_27) query;
933
+ (Result_28) query;
887
934
  getDayFromWeeklyTemplate: (args: GetDayFromWeeklyTemplateArgs) ->
888
- (Result_26) query;
935
+ (Result_27) query;
889
936
  /// Returns the effective availability mask (daily override or weekly template fallback)
890
937
  getEffectiveMaskForSalon: (args: GetEffectiveMaskForSalonArgs) ->
891
- (Result_25) query;
938
+ (Result_26) query;
892
939
  /// Returns the highest migrationId for the given entity (= total number of records ever created)
893
940
  getLastMigrationId: (entity: MigrationEntity) -> (Result_3) query;
894
941
  getLoggingEnabled: () -> (Result_1) query;
895
942
  getLogs: () -> (text) query;
896
943
  /// Returns a page of migration data for the given entity and id range [from, to]
897
- getMigrationData: (args: MigrationQueryArgs) -> (Result_24) query;
898
- getMyAppointments: () -> (Result_23) query;
944
+ getMigrationData: (args: MigrationQueryArgs) -> (Result_25) query;
945
+ getMyAppointments: () -> (Result_24) query;
899
946
  getMyProfile: () -> (Result_2) query;
900
947
  getMySalons: () -> (Result_17) query;
901
948
  getMyWorkerAppointments: (args: GetMyWorkerAppointmentsArgs) ->
902
- (Result_23) query;
949
+ (Result_24) query;
903
950
  /// Whether the one-way production switch has been flipped
904
951
  getProdMode: () -> (bool) query;
905
952
  /// Public geo feed: promos in the given geohash6 cells (search pattern — the frontend
906
953
  /// picks and adapts the cell set; core does exact-key lookups only)
907
954
  getPromoFeed: (args: GetPromoFeedArgs) -> (Result_19) query;
908
- getReportSettings: () -> (Result_22) query;
955
+ getReportSettings: () -> (Result_23) query;
909
956
  /// Returns the salon's asset library (readable only by the salon's current owner)
910
- getSalonAssets: (salonId: SalonId) -> (Result_21) query;
957
+ getSalonAssets: (salonId: SalonId) -> (Result_22) query;
911
958
  /// Owner-only: the salon's discount codes (semi-secret until broadcast via a promo)
912
- getSalonDiscountCodes: (salonId: SalonId) -> (Result_20) query;
913
- /// Public: the salon's current promos
959
+ getSalonDiscountCodes: (salonId: SalonId) -> (Result_21) query;
960
+ /// The salon's outstanding invite, or null when there is none or it has expired (Owner only)
961
+ getSalonInvite: (salonId: SalonId) -> (Result_20) query;
962
+ getSalonInviteTtl: () -> (Result_3) query;
963
+ /// The salon's promos: the whole library for its owner, the active ones for everyone else
914
964
  getSalonPromos: (salonId: SalonId) -> (Result_19) query;
915
965
  /// Returns the list of salon services by salon ID (owner view)
916
966
  getSalonServicesBySalonId: (salonId: SalonId) -> (Result_6) query;
@@ -951,7 +1001,7 @@ service : {
951
1001
  removeDailySchedule: (args: RemoveDailyScheduleArgs) -> (Result_1);
952
1002
  /// Owner removes a code (blocked while a promo of the salon still broadcasts it)
953
1003
  removeDiscountCode: (args: RemoveDiscountCodeArgs) -> (Result_1);
954
- /// Owner removes a promo (this is also the "deactivate"); the library asset stays
1004
+ /// Owner deletes a promo for good (to only hide it, use setPromoActive); the asset stays
955
1005
  removePromo: (args: RemovePromoArgs) -> (Result_1);
956
1006
  /// Permanently removes a salon service and cleans up search indexes
957
1007
  removeSalonServiceBySalonServiceId: (salonServiceId: SalonServiceId) ->
@@ -964,7 +1014,7 @@ service : {
964
1014
  removeWorkerFromSalonService: (args: AddOrRemoveWorkerInSalonArgs) ->
965
1015
  (Result_1);
966
1016
  reportOperationStats: (args: vec RecordOperationStatArgs) -> (Result_3);
967
- /// Worker sends a request to join a specific salon
1017
+ /// The one way to become a candidate: follow the owner's invite link (args carry its token)
968
1018
  requestToJoinSalon: (args: RequestToJoinArgs) -> (Result_1);
969
1019
  /// Superadmin-only: wipes all call-activity counters and restarts the tracking window from now, returns the new trackingSinceNs
970
1020
  resetCallActivityStats: () -> (Result_7);
@@ -983,8 +1033,12 @@ service : {
983
1033
  /// Superadmin only, ONE-WAY: flips isProd to true — the test-only endpoints
984
1034
  /// (purgeFailedAssetsNow, triggerAssetsSweep) trap from then on. There is no way back.
985
1035
  setProdMode: () -> (Result_1);
1036
+ /// Owner puts a promo in the feed or takes it out (max 3 active per salon); the promo
1037
+ /// itself stays in the library either way
1038
+ setPromoActive: (args: SetPromoActiveArgs) -> (Result_1);
986
1039
  setReportBatchSize: (size: nat) -> (Result_3);
987
1040
  setReportThreshold: (args: SetReportThresholdArgs) -> (Result_3);
1041
+ setSalonInviteTtl: (newTtlSeconds: nat) -> (Result_3);
988
1042
  /// Owner-only: set/clear the salon's profile photos (thumbnail + cover) — asset ids must
989
1043
  /// be #Ready Image assets from the salon's own library.
990
1044
  setSalonPhotos: (args: SetSalonPhotosArgs) -> (Result_5);
@@ -998,6 +1052,8 @@ service : {
998
1052
  /// sweep now, with a TTL override — same code path its hourly timer drives
999
1053
  triggerAssetsSweep: (ttlSeconds: nat) -> (Result_3);
1000
1054
  updateMyProfile: (args: UpdateProfileArgs) -> (Result_2);
1055
+ /// Owner edits a promo in place; it keeps its id, its createdAt and its place in the feed
1056
+ updatePromo: (args: UpdatePromoArgs) -> (Result_1);
1001
1057
  /// Updates an existing service with new details and synchronizes the index
1002
1058
  updateSalonService: (args: UpdateSalonServiceArgs) -> (Result_1);
1003
1059
  updateVisit: (args: UpdateVisitArgs) -> (Result);
@@ -117,6 +117,7 @@ export interface CanUploadAssetArgs {
117
117
  'declaredSizeBytes' : [] | [bigint],
118
118
  'salonId' : SalonId,
119
119
  }
120
+ export interface CheckSalonInviteArgs { 'token' : string, 'salonId' : SalonId }
120
121
  export interface Coordinate { 'lat' : number, 'lng' : number }
121
122
  export interface CreateSalonArgs {
122
123
  'name' : string,
@@ -264,6 +265,7 @@ export interface PromoItem {
264
265
  'cta' : PromoCta,
265
266
  'textLines' : Array<string>,
266
267
  'thumbId' : AssetId,
268
+ 'active' : boolean,
267
269
  'assetId' : AssetId,
268
270
  'chips' : Array<string>,
269
271
  'kind' : AssetKind,
@@ -310,7 +312,7 @@ export interface RemoveWorkerFromSalonArgs {
310
312
  'workerId' : Principal,
311
313
  'salonId' : SalonId,
312
314
  }
313
- export interface RequestToJoinArgs { 'salonId' : SalonId }
315
+ export interface RequestToJoinArgs { 'token' : string, 'salonId' : SalonId }
314
316
  export type Result = { 'ok' : VisitId } |
315
317
  { 'err' : Error };
316
318
  export type Result_1 = { 'ok' : boolean } |
@@ -337,11 +339,13 @@ export type Result_19 = { 'ok' : Array<PromoItem> } |
337
339
  { 'err' : Error };
338
340
  export type Result_2 = { 'ok' : UserProfile } |
339
341
  { 'err' : Error };
340
- export type Result_20 = { 'ok' : Array<DiscountCode> } |
342
+ export type Result_20 = { 'ok' : [] | [SalonInvite] } |
343
+ { 'err' : Error };
344
+ export type Result_21 = { 'ok' : Array<DiscountCode> } |
341
345
  { 'err' : Error };
342
- export type Result_21 = { 'ok' : Array<SalonAsset> } |
346
+ export type Result_22 = { 'ok' : Array<SalonAsset> } |
343
347
  { 'err' : Error };
344
- export type Result_22 = {
348
+ export type Result_23 = {
345
349
  'ok' : {
346
350
  'queryThresholdMs' : bigint,
347
351
  'updateThresholdMs' : bigint,
@@ -349,35 +353,37 @@ export type Result_22 = {
349
353
  }
350
354
  } |
351
355
  { 'err' : Error };
352
- export type Result_23 = { 'ok' : Array<Appointment> } |
356
+ export type Result_24 = { 'ok' : Array<Appointment> } |
353
357
  { 'err' : Error };
354
- export type Result_24 = { 'ok' : MigrationData } |
358
+ export type Result_25 = { 'ok' : MigrationData } |
355
359
  { 'err' : Error };
356
- export type Result_25 = { 'ok' : TimeMask } |
360
+ export type Result_26 = { 'ok' : TimeMask } |
357
361
  { 'err' : Error };
358
- export type Result_26 = { 'ok' : BigUint64Array | bigint[] } |
362
+ export type Result_27 = { 'ok' : BigUint64Array | bigint[] } |
359
363
  { 'err' : Error };
360
- export type Result_27 = { 'ok' : Array<DailyScheduleEntry> } |
364
+ export type Result_28 = { 'ok' : Array<DailyScheduleEntry> } |
361
365
  { 'err' : Error };
362
- export type Result_28 = {
366
+ export type Result_29 = {
363
367
  'ok' : { 'entries' : Array<CallActivityEntry>, 'trackingSinceNs' : bigint }
364
368
  } |
365
369
  { 'err' : Error };
366
- export type Result_29 = { 'ok' : Array<SupportedLanguage> } |
367
- { 'err' : Error };
368
370
  export type Result_3 = { 'ok' : bigint } |
369
371
  { 'err' : Error };
370
- export type Result_30 = { 'ok' : ActionQuotaLimits } |
372
+ export type Result_30 = { 'ok' : Array<SupportedLanguage> } |
373
+ { 'err' : Error };
374
+ export type Result_31 = { 'ok' : ActionQuotaLimits } |
371
375
  { 'err' : Error };
372
- export type Result_31 = { 'ok' : AppointmentId } |
376
+ export type Result_32 = { 'ok' : SalonInvite } |
373
377
  { 'err' : Error };
374
- export type Result_32 = { 'ok' : Array<SalonId> } |
378
+ export type Result_33 = { 'ok' : AppointmentId } |
375
379
  { 'err' : Error };
376
- export type Result_33 = { 'ok' : Array<SalonServiceId> } |
380
+ export type Result_34 = { 'ok' : Array<SalonId> } |
377
381
  { 'err' : Error };
378
- export type Result_34 = { 'ok' : SalonServiceId } |
382
+ export type Result_35 = { 'ok' : Array<SalonServiceId> } |
379
383
  { 'err' : Error };
380
- export type Result_35 = { 'ok' : PromoId } |
384
+ export type Result_36 = { 'ok' : SalonServiceId } |
385
+ { 'err' : Error };
386
+ export type Result_37 = { 'ok' : PromoId } |
381
387
  { 'err' : Error };
382
388
  export type Result_4 = { 'ok' : Principal } |
383
389
  { 'err' : Error };
@@ -423,6 +429,7 @@ export interface SalonCandidatesEntry {
423
429
  'salonId' : SalonId,
424
430
  }
425
431
  export type SalonId = string;
432
+ export interface SalonInvite { 'expiresAtNs' : bigint, 'token' : string }
426
433
  export interface SalonPublicInfo {
427
434
  'id' : SalonId,
428
435
  'name' : string,
@@ -473,6 +480,11 @@ export interface SetDailyScheduleArgs {
473
480
  'mask' : TimeMask,
474
481
  }
475
482
  export interface SetLanguageActiveArgs { 'active' : boolean, 'code' : LangCode }
483
+ export interface SetPromoActiveArgs {
484
+ 'active' : boolean,
485
+ 'salonId' : SalonId,
486
+ 'promoId' : PromoId,
487
+ }
476
488
  export interface SetReportThresholdArgs {
477
489
  'opType' : OperationType,
478
490
  'thresholdMs' : bigint,
@@ -510,6 +522,15 @@ export interface UpdateProfileArgs {
510
522
  'name' : string,
511
523
  'avatarUrl' : [] | [string],
512
524
  }
525
+ export interface UpdatePromoArgs {
526
+ 'cta' : PromoCta,
527
+ 'textLines' : Array<string>,
528
+ 'assetId' : AssetId,
529
+ 'chips' : Array<string>,
530
+ 'target' : PromoTarget,
531
+ 'salonId' : SalonId,
532
+ 'promoId' : PromoId,
533
+ }
513
534
  export interface UpdateSalonServiceArgs {
514
535
  'duration' : bigint,
515
536
  'active' : boolean,
@@ -590,14 +611,15 @@ export interface _SERVICE {
590
611
  */
591
612
  'addLanguage' : ActorMethod<[LangCode], Result_1>,
592
613
  /**
593
- * / Owner attaches a promo (max 3 per salon): #Ready media from the salon's library,
594
- * / target = the salon or one of its services, CTA = button label / show-delay / discount code
614
+ * / Owner adds a promo to the salon's library (max 15): #Ready media from the salon's
615
+ * / library, target = the salon or one of its services, CTA = button label / discount code.
616
+ * / The promo is created INACTIVE — setPromoActive is what puts it in the feed
595
617
  */
596
- 'addPromo' : ActorMethod<[AddPromoArgs], Result_35>,
618
+ 'addPromo' : ActorMethod<[AddPromoArgs], Result_37>,
597
619
  /**
598
620
  * / Adds a new service to a specific salon
599
621
  */
600
- 'addSalonService' : ActorMethod<[AddSalonServiceArgs], Result_34>,
622
+ 'addSalonService' : ActorMethod<[AddSalonServiceArgs], Result_36>,
601
623
  'addServiceType' : ActorMethod<[ServiceTypeId], Result_1>,
602
624
  'addServiceTypeToSalonService' : ActorMethod<
603
625
  [AddOrRemoveServiceTypeInSalonArgs],
@@ -614,11 +636,11 @@ export interface _SERVICE {
614
636
  [AttachOrDetachImageArgs],
615
637
  Result_1
616
638
  >,
617
- 'bookAppointment' : ActorMethod<[BookAppointmentArgs], Result_31>,
639
+ 'bookAppointment' : ActorMethod<[BookAppointmentArgs], Result_33>,
618
640
  'bulkAcceptWorkers' : ActorMethod<[BulkAcceptWorkersArgs], Result_1>,
619
- 'bulkAddSalonServices' : ActorMethod<[BulkAddSalonServicesArgs], Result_33>,
641
+ 'bulkAddSalonServices' : ActorMethod<[BulkAddSalonServicesArgs], Result_35>,
620
642
  'bulkAddServiceTypes' : ActorMethod<[Array<ServiceTypeId>], Result_14>,
621
- 'bulkCreateSalons' : ActorMethod<[BulkCreateSalonsArgs], Result_32>,
643
+ 'bulkCreateSalons' : ActorMethod<[BulkCreateSalonsArgs], Result_34>,
622
644
  'bulkRequestToJoinSalons' : ActorMethod<
623
645
  [BulkRequestToJoinSalonsArgs],
624
646
  Result_1
@@ -635,12 +657,21 @@ export interface _SERVICE {
635
657
  * / Asset canister only: pre-upload authorization, asked before any bytes are stored
636
658
  */
637
659
  'canUploadAsset' : ActorMethod<[CanUploadAssetArgs], Result_1>,
638
- 'cancelAppointment' : ActorMethod<[AppointmentId], Result_31>,
660
+ 'cancelAppointment' : ActorMethod<[AppointmentId], Result_33>,
661
+ /**
662
+ * / Is an invite link still good? Open to anonymous callers — the page behind the link has
663
+ * / to answer before there is an identity to ask about.
664
+ */
665
+ 'checkSalonInvite' : ActorMethod<[CheckSalonInviteArgs], Result_1>,
639
666
  'clearLogs' : ActorMethod<[], undefined>,
640
667
  /**
641
668
  * / Creates a new salon and links it to the caller
642
669
  */
643
670
  'createSalon' : ActorMethod<[CreateSalonArgs], Result_5>,
671
+ /**
672
+ * / Owner mints the salon's worker-invite link (replaces any outstanding one)
673
+ */
674
+ 'createSalonInvite' : ActorMethod<[SalonId], Result_32>,
644
675
  'createVisit' : ActorMethod<[CreateVisitArgs], Result>,
645
676
  /**
646
677
  * / Superadmin only: raw byte removal on sultana-assets-rust (orphaned-bytes cleanup)
@@ -662,21 +693,21 @@ export interface _SERVICE {
662
693
  [AttachOrDetachImageArgs],
663
694
  Result_1
664
695
  >,
665
- 'getActionQuotaLimits' : ActorMethod<[], Result_30>,
696
+ 'getActionQuotaLimits' : ActorMethod<[], Result_31>,
666
697
  /**
667
698
  * / Superadmin: every supported language incl. inactive ones (admin panel view)
668
699
  */
669
- 'getAllLanguages' : ActorMethod<[], Result_29>,
700
+ 'getAllLanguages' : ActorMethod<[], Result_30>,
670
701
  'getAllProfiles' : ActorMethod<[], Result_8>,
671
702
  'getAppointmentsForSalon' : ActorMethod<
672
703
  [GetSalonAppointmentsArgs],
673
- Result_23
704
+ Result_24
674
705
  >,
675
706
  'getAssetCanisterPrincipal' : ActorMethod<[], Result_4>,
676
707
  /**
677
708
  * / Superadmin-only: returns every principal's lifetime (total, productive) call counters plus the tracking window start
678
709
  */
679
- 'getCallActivityStats' : ActorMethod<[], Result_28>,
710
+ 'getCallActivityStats' : ActorMethod<[], Result_29>,
680
711
  /**
681
712
  * / Returns the list of profiles waiting for approval (Owner only)
682
713
  */
@@ -684,24 +715,24 @@ export interface _SERVICE {
684
715
  /**
685
716
  * / Returns a specific daily override if it exists
686
717
  */
687
- 'getDailySchedule' : ActorMethod<[GetDailyScheduleArgs], Result_25>,
718
+ 'getDailySchedule' : ActorMethod<[GetDailyScheduleArgs], Result_26>,
688
719
  /**
689
720
  * / Returns daily schedules with midnight timestamp in [fromDate, toDate] - for data migration to another canister
690
721
  */
691
722
  'getDailySchedulesForMigration' : ActorMethod<
692
723
  [DailyScheduleRangeArgs],
693
- Result_27
724
+ Result_28
694
725
  >,
695
726
  'getDayFromWeeklyTemplate' : ActorMethod<
696
727
  [GetDayFromWeeklyTemplateArgs],
697
- Result_26
728
+ Result_27
698
729
  >,
699
730
  /**
700
731
  * / Returns the effective availability mask (daily override or weekly template fallback)
701
732
  */
702
733
  'getEffectiveMaskForSalon' : ActorMethod<
703
734
  [GetEffectiveMaskForSalonArgs],
704
- Result_25
735
+ Result_26
705
736
  >,
706
737
  /**
707
738
  * / Returns the highest migrationId for the given entity (= total number of records ever created)
@@ -712,13 +743,13 @@ export interface _SERVICE {
712
743
  /**
713
744
  * / Returns a page of migration data for the given entity and id range [from, to]
714
745
  */
715
- 'getMigrationData' : ActorMethod<[MigrationQueryArgs], Result_24>,
716
- 'getMyAppointments' : ActorMethod<[], Result_23>,
746
+ 'getMigrationData' : ActorMethod<[MigrationQueryArgs], Result_25>,
747
+ 'getMyAppointments' : ActorMethod<[], Result_24>,
717
748
  'getMyProfile' : ActorMethod<[], Result_2>,
718
749
  'getMySalons' : ActorMethod<[], Result_17>,
719
750
  'getMyWorkerAppointments' : ActorMethod<
720
751
  [GetMyWorkerAppointmentsArgs],
721
- Result_23
752
+ Result_24
722
753
  >,
723
754
  /**
724
755
  * / Whether the one-way production switch has been flipped
@@ -729,17 +760,22 @@ export interface _SERVICE {
729
760
  * / picks and adapts the cell set; core does exact-key lookups only)
730
761
  */
731
762
  'getPromoFeed' : ActorMethod<[GetPromoFeedArgs], Result_19>,
732
- 'getReportSettings' : ActorMethod<[], Result_22>,
763
+ 'getReportSettings' : ActorMethod<[], Result_23>,
733
764
  /**
734
765
  * / Returns the salon's asset library (readable only by the salon's current owner)
735
766
  */
736
- 'getSalonAssets' : ActorMethod<[SalonId], Result_21>,
767
+ 'getSalonAssets' : ActorMethod<[SalonId], Result_22>,
737
768
  /**
738
769
  * / Owner-only: the salon's discount codes (semi-secret until broadcast via a promo)
739
770
  */
740
- 'getSalonDiscountCodes' : ActorMethod<[SalonId], Result_20>,
771
+ 'getSalonDiscountCodes' : ActorMethod<[SalonId], Result_21>,
772
+ /**
773
+ * / The salon's outstanding invite, or null when there is none or it has expired (Owner only)
774
+ */
775
+ 'getSalonInvite' : ActorMethod<[SalonId], Result_20>,
776
+ 'getSalonInviteTtl' : ActorMethod<[], Result_3>,
741
777
  /**
742
- * / Public: the salon's current promos
778
+ * / The salon's promos: the whole library for its owner, the active ones for everyone else
743
779
  */
744
780
  'getSalonPromos' : ActorMethod<[SalonId], Result_19>,
745
781
  /**
@@ -808,7 +844,7 @@ export interface _SERVICE {
808
844
  */
809
845
  'removeDiscountCode' : ActorMethod<[RemoveDiscountCodeArgs], Result_1>,
810
846
  /**
811
- * / Owner removes a promo (this is also the "deactivate"); the library asset stays
847
+ * / Owner deletes a promo for good (to only hide it, use setPromoActive); the asset stays
812
848
  */
813
849
  'removePromo' : ActorMethod<[RemovePromoArgs], Result_1>,
814
850
  /**
@@ -836,7 +872,7 @@ export interface _SERVICE {
836
872
  Result_3
837
873
  >,
838
874
  /**
839
- * / Worker sends a request to join a specific salon
875
+ * / The one way to become a candidate: follow the owner's invite link (args carry its token)
840
876
  */
841
877
  'requestToJoinSalon' : ActorMethod<[RequestToJoinArgs], Result_1>,
842
878
  /**
@@ -868,8 +904,14 @@ export interface _SERVICE {
868
904
  * / (purgeFailedAssetsNow, triggerAssetsSweep) trap from then on. There is no way back.
869
905
  */
870
906
  'setProdMode' : ActorMethod<[], Result_1>,
907
+ /**
908
+ * / Owner puts a promo in the feed or takes it out (max 3 active per salon); the promo
909
+ * / itself stays in the library either way
910
+ */
911
+ 'setPromoActive' : ActorMethod<[SetPromoActiveArgs], Result_1>,
871
912
  'setReportBatchSize' : ActorMethod<[bigint], Result_3>,
872
913
  'setReportThreshold' : ActorMethod<[SetReportThresholdArgs], Result_3>,
914
+ 'setSalonInviteTtl' : ActorMethod<[bigint], Result_3>,
873
915
  /**
874
916
  * / Owner-only: set/clear the salon's profile photos (thumbnail + cover) — asset ids must
875
917
  * / be #Ready Image assets from the salon's own library.
@@ -889,6 +931,10 @@ export interface _SERVICE {
889
931
  */
890
932
  'triggerAssetsSweep' : ActorMethod<[bigint], Result_3>,
891
933
  'updateMyProfile' : ActorMethod<[UpdateProfileArgs], Result_2>,
934
+ /**
935
+ * / Owner edits a promo in place; it keeps its id, its createdAt and its place in the feed
936
+ */
937
+ 'updatePromo' : ActorMethod<[UpdatePromoArgs], Result_1>,
892
938
  /**
893
939
  * / Updates an existing service with new details and synchronizes the index
894
940
  */