founder-schema 0.17.0 → 0.19.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 (120) hide show
  1. package/README.md +186 -17
  2. package/dist/access/access.d.ts +1 -1
  3. package/dist/access/access.d.ts.map +1 -1
  4. package/dist/access/access.js +4 -1
  5. package/dist/access/access.js.map +1 -1
  6. package/dist/access/permissions.d.ts +27 -29
  7. package/dist/access/permissions.d.ts.map +1 -1
  8. package/dist/access/permissions.js +39 -3
  9. package/dist/access/permissions.js.map +1 -1
  10. package/dist/core/common.d.ts +54 -23
  11. package/dist/core/common.d.ts.map +1 -1
  12. package/dist/core/common.js +49 -24
  13. package/dist/core/common.js.map +1 -1
  14. package/dist/core/errors.d.ts +7 -5
  15. package/dist/core/errors.d.ts.map +1 -1
  16. package/dist/core/errors.js +17 -11
  17. package/dist/core/errors.js.map +1 -1
  18. package/dist/core/limits.d.ts +73 -17
  19. package/dist/core/limits.d.ts.map +1 -1
  20. package/dist/core/limits.js +77 -22
  21. package/dist/core/limits.js.map +1 -1
  22. package/dist/core/money.d.ts +33 -0
  23. package/dist/core/money.d.ts.map +1 -0
  24. package/dist/core/money.js +36 -0
  25. package/dist/core/money.js.map +1 -0
  26. package/dist/core/responses.d.ts +14 -4
  27. package/dist/core/responses.d.ts.map +1 -1
  28. package/dist/core/responses.js.map +1 -1
  29. package/dist/core/validation.d.ts +19 -2
  30. package/dist/core/validation.d.ts.map +1 -1
  31. package/dist/core/validation.js +19 -2
  32. package/dist/core/validation.js.map +1 -1
  33. package/dist/domains/billing/billing.d.ts +61 -8
  34. package/dist/domains/billing/billing.d.ts.map +1 -1
  35. package/dist/domains/billing/billing.js +58 -22
  36. package/dist/domains/billing/billing.js.map +1 -1
  37. package/dist/domains/billing/gst.d.ts.map +1 -1
  38. package/dist/domains/billing/gst.js +4 -3
  39. package/dist/domains/billing/gst.js.map +1 -1
  40. package/dist/domains/chat/chat.d.ts +0 -21
  41. package/dist/domains/chat/chat.d.ts.map +1 -1
  42. package/dist/domains/chat/chat.js +0 -20
  43. package/dist/domains/chat/chat.js.map +1 -1
  44. package/dist/domains/communities/communities.d.ts +30 -12
  45. package/dist/domains/communities/communities.d.ts.map +1 -1
  46. package/dist/domains/communities/communities.js +43 -15
  47. package/dist/domains/communities/communities.js.map +1 -1
  48. package/dist/domains/contributions/contributions.d.ts +1 -1
  49. package/dist/domains/contributions/contributions.js +1 -1
  50. package/dist/domains/contributions/contributions.js.map +1 -1
  51. package/dist/domains/dashboard/dashboard.d.ts +3 -1
  52. package/dist/domains/dashboard/dashboard.d.ts.map +1 -1
  53. package/dist/domains/dashboard/dashboard.js +23 -7
  54. package/dist/domains/dashboard/dashboard.js.map +1 -1
  55. package/dist/domains/discover/discover.d.ts +8 -8
  56. package/dist/domains/feed/feed.d.ts +55 -153
  57. package/dist/domains/feed/feed.d.ts.map +1 -1
  58. package/dist/domains/feed/feed.js +53 -58
  59. package/dist/domains/feed/feed.js.map +1 -1
  60. package/dist/domains/location/areas.d.ts +331 -0
  61. package/dist/domains/location/areas.d.ts.map +1 -0
  62. package/dist/domains/location/areas.js +238 -0
  63. package/dist/domains/location/areas.js.map +1 -0
  64. package/dist/domains/location/india.d.ts +41 -123
  65. package/dist/domains/location/india.d.ts.map +1 -1
  66. package/dist/domains/location/india.js +121 -59
  67. package/dist/domains/location/india.js.map +1 -1
  68. package/dist/domains/members/members.d.ts +2 -2
  69. package/dist/domains/membership/membership.d.ts +26 -0
  70. package/dist/domains/membership/membership.d.ts.map +1 -1
  71. package/dist/domains/membership/membership.js +55 -1
  72. package/dist/domains/membership/membership.js.map +1 -1
  73. package/dist/domains/moderation/moderation.d.ts +2 -2
  74. package/dist/domains/moderation/moderation.js +3 -3
  75. package/dist/domains/moderation/moderation.js.map +1 -1
  76. package/dist/domains/notifications/notifications.d.ts +1 -10
  77. package/dist/domains/notifications/notifications.d.ts.map +1 -1
  78. package/dist/domains/notifications/notifications.js +2 -3
  79. package/dist/domains/notifications/notifications.js.map +1 -1
  80. package/dist/domains/onboarding/onboarding-answers.d.ts +42 -14
  81. package/dist/domains/onboarding/onboarding-answers.d.ts.map +1 -1
  82. package/dist/domains/onboarding/onboarding-answers.js +49 -33
  83. package/dist/domains/onboarding/onboarding-answers.js.map +1 -1
  84. package/dist/domains/onboarding/onboarding.d.ts +332 -138
  85. package/dist/domains/onboarding/onboarding.d.ts.map +1 -1
  86. package/dist/domains/onboarding/onboarding.js +47 -59
  87. package/dist/domains/onboarding/onboarding.js.map +1 -1
  88. package/dist/domains/products/products.d.ts +43 -8
  89. package/dist/domains/products/products.d.ts.map +1 -1
  90. package/dist/domains/products/products.js +57 -11
  91. package/dist/domains/products/products.js.map +1 -1
  92. package/dist/domains/profile/founder-profile.d.ts +123 -143
  93. package/dist/domains/profile/founder-profile.d.ts.map +1 -1
  94. package/dist/domains/profile/founder-profile.js +77 -35
  95. package/dist/domains/profile/founder-profile.js.map +1 -1
  96. package/dist/domains/profile/my-profile.d.ts +3 -3
  97. package/dist/domains/reviews/reviews.d.ts +1 -1
  98. package/dist/domains/reviews/reviews.d.ts.map +1 -1
  99. package/dist/domains/reviews/reviews.js +2 -2
  100. package/dist/domains/reviews/reviews.js.map +1 -1
  101. package/dist/domains/support/support.d.ts +22 -3
  102. package/dist/domains/support/support.d.ts.map +1 -1
  103. package/dist/domains/support/support.js +19 -5
  104. package/dist/domains/support/support.js.map +1 -1
  105. package/dist/domains/team/team.d.ts.map +1 -1
  106. package/dist/domains/team/team.js +3 -6
  107. package/dist/domains/team/team.js.map +1 -1
  108. package/dist/domains/uploads/uploads.d.ts +7 -22
  109. package/dist/domains/uploads/uploads.d.ts.map +1 -1
  110. package/dist/domains/uploads/uploads.js +7 -21
  111. package/dist/domains/uploads/uploads.js.map +1 -1
  112. package/dist/env.d.ts +26 -13
  113. package/dist/env.d.ts.map +1 -1
  114. package/dist/env.js +58 -23
  115. package/dist/env.js.map +1 -1
  116. package/dist/index.d.ts +19 -17
  117. package/dist/index.d.ts.map +1 -1
  118. package/dist/index.js +21 -17
  119. package/dist/index.js.map +1 -1
  120. package/package.json +1 -1
@@ -16,9 +16,11 @@
16
16
  * joining one tap request, then invite only,
17
17
  * approval then accept
18
18
  *
19
- * Taking part (post, poll, comment, react, vote, save, report) is for
20
- * members of every type. "Members" means ACTIVE members: someone who
21
- * requested, was invited or is banned is a non-member for every rule.
19
+ * Taking part (post, poll, comment, react, vote, save) is for members of
20
+ * every type. "Members" means ACTIVE members: someone who requested, was
21
+ * invited or is banned is a non-member for every rule. Taking a reaction,
22
+ * a vote or a save BACK needs only read access, and reporting is open to
23
+ * any signed-in reader (safety, 0.13.0).
22
24
  * - PUBLIC MEANS PUBLIC INSIDE FOUNDER CIRCLE: a signed-out visitor sees no
23
25
  * community content of any type, even by a shared link.
24
26
  * - THE HOME FEED adds only the communities the member joined.
@@ -174,11 +176,25 @@ export declare const communityStatusSchema: z.ZodEnum<{
174
176
  archived: "archived";
175
177
  }>;
176
178
  export type CommunityStatus = z.infer<typeof communityStatusSchema>;
179
+ /**
180
+ * Whether a community may take type `to` now (0.18.0): ONE rule for the
181
+ * server's refusal (`COMMUNITY_ARCHIVED`) and the screen's choice. An
182
+ * archived community lets nobody new in, so it may be narrowed (private,
183
+ * hidden) but never opened to public, which would let its waiting requests in.
184
+ */
185
+ export declare function communityTypeChangeAllowed(status: CommunityStatus, to: CommunityVisibility): boolean;
186
+ /** How staff decided a suggestion (0.18.0: named, for the bell and the backend's model). */
187
+ export declare const COMMUNITY_SUGGESTION_DECISION_VALUES: readonly ["approved", "declined"];
188
+ export declare const communitySuggestionDecisionSchema: z.ZodEnum<{
189
+ approved: "approved";
190
+ declined: "declined";
191
+ }>;
192
+ export type CommunitySuggestionDecision = z.infer<typeof communitySuggestionDecisionSchema>;
177
193
  export declare const COMMUNITY_SUGGESTION_STATUS_VALUES: readonly ["open", "approved", "declined"];
178
194
  export declare const communitySuggestionStatusSchema: z.ZodEnum<{
179
- open: "open";
180
195
  approved: "approved";
181
196
  declined: "declined";
197
+ open: "open";
182
198
  }>;
183
199
  export type CommunitySuggestionStatus = z.infer<typeof communitySuggestionStatusSchema>;
184
200
  /**
@@ -349,6 +365,7 @@ export declare const communityViewerSchema: z.ZodObject<{
349
365
  canRequest: z.ZodBoolean;
350
366
  canPost: z.ZodBoolean;
351
367
  canLeave: z.ZodBoolean;
368
+ leaveArchives: z.ZodBoolean;
352
369
  canModerate: z.ZodBoolean;
353
370
  canManage: z.ZodBoolean;
354
371
  canAssign: z.ZodBoolean;
@@ -523,6 +540,7 @@ export declare const communitySchema: z.ZodObject<{
523
540
  canRequest: z.ZodBoolean;
524
541
  canPost: z.ZodBoolean;
525
542
  canLeave: z.ZodBoolean;
543
+ leaveArchives: z.ZodBoolean;
526
544
  canModerate: z.ZodBoolean;
527
545
  canManage: z.ZodBoolean;
528
546
  canAssign: z.ZodBoolean;
@@ -725,9 +743,9 @@ export declare const communitySuggestionSchema: z.ZodObject<{
725
743
  education_access: "education_access";
726
744
  }>>;
727
745
  status: z.ZodEnum<{
728
- open: "open";
729
746
  approved: "approved";
730
747
  declined: "declined";
748
+ open: "open";
731
749
  }>;
732
750
  decidedBy: z.ZodNullable<z.ZodObject<{
733
751
  userId: z.ZodString;
@@ -1040,9 +1058,9 @@ export declare const communitySuggestionPageSchema: z.ZodObject<{
1040
1058
  education_access: "education_access";
1041
1059
  }>>;
1042
1060
  status: z.ZodEnum<{
1043
- open: "open";
1044
1061
  approved: "approved";
1045
1062
  declined: "declined";
1063
+ open: "open";
1046
1064
  }>;
1047
1065
  decidedBy: z.ZodNullable<z.ZodObject<{
1048
1066
  userId: z.ZodString;
@@ -1077,8 +1095,8 @@ export type CommunitySuggestionPage = z.infer<typeof communitySuggestionPageSche
1077
1095
  */
1078
1096
  export declare const communityDiscoverQuerySchema: z.ZodObject<{
1079
1097
  limit: z.ZodPreprocess<z.ZodDefault<z.ZodCoercedNumber<unknown>>, unknown>;
1080
- cursor: z.ZodOptional<z.ZodString>;
1081
- q: z.ZodPreprocess<z.ZodOptional<z.ZodString>, unknown>;
1098
+ cursor: z.ZodPreprocess<z.ZodOptional<z.ZodString>, unknown>;
1099
+ q: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>>;
1082
1100
  topic: z.ZodPreprocess<z.ZodOptional<z.ZodArray<z.ZodEnum<{
1083
1101
  ai_ml: "ai_ml";
1084
1102
  b2b_saas: "b2b_saas";
@@ -1157,7 +1175,7 @@ export type CommunityDiscoverQueryInput = z.input<typeof communityDiscoverQueryS
1157
1175
  /** `GET /communities/:id/members`: everyone, or one role (`?role=admin`). */
1158
1176
  export declare const communityMembersQuerySchema: z.ZodObject<{
1159
1177
  limit: z.ZodPreprocess<z.ZodDefault<z.ZodCoercedNumber<unknown>>, unknown>;
1160
- cursor: z.ZodOptional<z.ZodString>;
1178
+ cursor: z.ZodPreprocess<z.ZodOptional<z.ZodString>, unknown>;
1161
1179
  role: z.ZodPreprocess<z.ZodOptional<z.ZodEnum<{
1162
1180
  admin: "admin";
1163
1181
  moderator: "moderator";
@@ -1169,11 +1187,11 @@ export type CommunityMembersQueryInput = z.input<typeof communityMembersQuerySch
1169
1187
  /** `GET /community-suggestions` (staff): waiting ones by default, oldest first. */
1170
1188
  export declare const communitySuggestionsQuerySchema: z.ZodObject<{
1171
1189
  limit: z.ZodPreprocess<z.ZodDefault<z.ZodCoercedNumber<unknown>>, unknown>;
1172
- cursor: z.ZodOptional<z.ZodString>;
1190
+ cursor: z.ZodPreprocess<z.ZodOptional<z.ZodString>, unknown>;
1173
1191
  status: z.ZodPreprocess<z.ZodDefault<z.ZodEnum<{
1174
- open: "open";
1175
1192
  approved: "approved";
1176
1193
  declined: "declined";
1194
+ open: "open";
1177
1195
  }>>, unknown>;
1178
1196
  }, z.core.$strip>;
1179
1197
  export type CommunitySuggestionsQuery = z.infer<typeof communitySuggestionsQuerySchema>;
@@ -1427,7 +1445,7 @@ export type SetCommunityMemberRoleBody = z.infer<typeof setCommunityMemberRoleBo
1427
1445
  /** `POST /communities/:id/bans` (admins): removes them if active, and keeps them out. */
1428
1446
  export declare const banCommunityMemberBodySchema: z.ZodObject<{
1429
1447
  userId: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
1430
- reason: z.ZodOptional<z.ZodString>;
1448
+ reason: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>>;
1431
1449
  }, z.core.$strip>;
1432
1450
  export type BanCommunityMemberBody = z.infer<typeof banCommunityMemberBodySchema>;
1433
1451
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"communities.d.ts","sourceRoot":"","sources":["../../../src/domains/communities/communities.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoHG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA2BxB,4DAA4D;AAC5D,eAAO,MAAM,oBAAoB,IAAI,CAAC;AACtC,gEAAgE;AAChE,eAAO,MAAM,kBAAkB,IAAI,CAAC;AACpC,kEAAkE;AAClE,eAAO,MAAM,8BAA8B,IAAI,CAAC;AAChD;;;GAGG;AACH,eAAO,MAAM,8BAA8B,QAAsB,CAAC;AAKlE,mCAAmC;AACnC,eAAO,MAAM,2BAA2B,0CAA2C,CAAC;AACpF,eAAO,MAAM,yBAAyB;;;;EAAsC,CAAC;AAC7E,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E;;;GAGG;AACH,eAAO,MAAM,yBAAyB;;;;CAIkB,CAAC;AAEzD,8EAA8E;AAC9E,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,mBAAmB,EACzB,EAAE,EAAE,mBAAmB,GACtB,OAAO,CAET;AAED,4CAA4C;AAC5C,eAAO,MAAM,qBAAqB,2CAA4C,CAAC;AAC/E,eAAO,MAAM,mBAAmB;;;;EAAgC,CAAC;AACjE,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE;;;;GAIG;AACH,eAAO,MAAM,8BAA8B,uDAAwD,CAAC;AACpG,eAAO,MAAM,2BAA2B;;;;;EAAyC,CAAC;AAClF,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF,oFAAoF;AACpF,eAAO,MAAM,uBAAuB,iCAAkC,CAAC;AACvE,eAAO,MAAM,qBAAqB;;;EAAkC,CAAC;AACrE,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,eAAO,MAAM,kCAAkC,2CAA4C,CAAC;AAC5F,eAAO,MAAM,+BAA+B;;;;EAA6C,CAAC;AAC1F,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAC;AAIxF;;;GAGG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;iBAS9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,yFAAyF;AACzF,eAAO,MAAM,yBAAyB;;;;;;;;;;;iBAKpC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E,yDAAyD;AACzD,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAc9B,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE;;;;GAIG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;iBAiChC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;iBAUhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,wFAAwF;AACxF,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAkB1B,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD,uEAAuE;AACvE,eAAO,MAAM,sBAAsB;;;;;;;;;iBAGjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,uEAAuE;AACvE,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;iBAKvC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAElF,qDAAqD;AACrD,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;iBAIhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,8FAA8F;AAC9F,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;iBAAsD,CAAC;AAC1F,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,6DAA6D;AAC7D,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;iBAM7B,CAAC;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE9D,4DAA4D;AAC5D,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAoBpC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAAuC,CAAC;AAC5E,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AACxE,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;iBAAyC,CAAC;AAChF,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAC5E,eAAO,MAAM,0BAA0B;;;;;;;;;;;;iBAA0C,CAAC;AAClF,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAC9E,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;iBAAgD,CAAC;AAC9F,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gCAAgC,CAAC,CAAC;AAC1F,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;iBAAsC,CAAC;AAC1E,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AACtE,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAA6C,CAAC;AACxF,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAIpF;;;;GAIG;AACH,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAGvC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAClF,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAEvF,6EAA6E;AAC7E,eAAO,MAAM,2BAA2B;;;;;;;;iBAEtC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAChF,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAErF,mFAAmF;AACnF,eAAO,MAAM,+BAA+B;;;;;;;;iBAE1C,CAAC;AACH,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAC;AACxF,MAAM,MAAM,8BAA8B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAC;AAE7F,eAAO,MAAM,qBAAqB;;iBAA4C,CAAC;AAC/E,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACpE,2EAA2E;AAC3E,eAAO,MAAM,2BAA2B;;;iBAGtC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAChF,6DAA6D;AAC7D,eAAO,MAAM,4BAA4B;;;iBAGvC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAClF,sEAAsE;AACtE,eAAO,MAAM,4BAA4B;;;iBAGvC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAClF,eAAO,MAAM,+BAA+B;;iBAA6C,CAAC;AAC1F,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAC;AAiBxF;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAOpC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E,0GAA0G;AAC1G,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAMpC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E,0GAA0G;AAC1G,eAAO,MAAM,0BAA0B;;iBAAwC,CAAC;AAChF,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAE9E;;;;;GAKG;AACH,eAAO,MAAM,gCAAgC;;;;;;;iBAG3C,CAAC;AACH,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gCAAgC,CAAC,CAAC;AAE1F,sDAAsD;AACtD,eAAO,MAAM,4BAA4B;;;;;iBAA8C,CAAC;AACxF,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAElF;;;;;;GAMG;AACH,eAAO,MAAM,+BAA+B;;iBAAuC,CAAC;AACpF,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAC;AAExF,kGAAkG;AAClG,eAAO,MAAM,gCAAgC;;;;;;iBAA0C,CAAC;AACxF,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gCAAgC,CAAC,CAAC;AAE1F,yFAAyF;AACzF,eAAO,MAAM,4BAA4B;;;iBAGvC,CAAC;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAElF;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B;;;iBAGxC,CAAC;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAEpF;;;GAGG;AACH,eAAO,MAAM,mCAAmC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAM9C,CAAC;AACH,MAAM,MAAM,6BAA6B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mCAAmC,CAAC,CAAC;AAEhG;;;GAGG;AACH,eAAO,MAAM,oCAAoC;;iBAE/C,CAAC;AACH,MAAM,MAAM,8BAA8B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oCAAoC,CAAC,CAAC"}
1
+ {"version":3,"file":"communities.d.ts","sourceRoot":"","sources":["../../../src/domains/communities/communities.ts"],"names":[],"mappings":"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"}
@@ -16,9 +16,11 @@
16
16
  * joining one tap request, then invite only,
17
17
  * approval then accept
18
18
  *
19
- * Taking part (post, poll, comment, react, vote, save, report) is for
20
- * members of every type. "Members" means ACTIVE members: someone who
21
- * requested, was invited or is banned is a non-member for every rule.
19
+ * Taking part (post, poll, comment, react, vote, save) is for members of
20
+ * every type. "Members" means ACTIVE members: someone who requested, was
21
+ * invited or is banned is a non-member for every rule. Taking a reaction,
22
+ * a vote or a save BACK needs only read access, and reporting is open to
23
+ * any signed-in reader (safety, 0.13.0).
22
24
  * - PUBLIC MEANS PUBLIC INSIDE FOUNDER CIRCLE: a signed-out visitor sees no
23
25
  * community content of any type, even by a shared link.
24
26
  * - THE HOME FEED adds only the communities the member joined.
@@ -116,8 +118,8 @@
116
118
  * @module founder-schema/domains/communities
117
119
  */
118
120
  import { z } from 'zod';
119
- import { emptyStringToUndefined, multiValueQuery, objectIdSchema, optionalTrimmedString, paginationQuerySchema, } from '../../core/common.js';
120
- import { COMMUNITY_BAN_REASON_MAX, COMMUNITY_DECLINE_REASON_MAX, COMMUNITY_DECLINE_REASON_MIN, COMMUNITY_DESCRIPTION_MAX, COMMUNITY_NAME_MAX, COMMUNITY_NAME_MIN, COMMUNITY_RULE_MAX, COMMUNITY_RULES_MAX, COMMUNITY_SUGGESTION_WHY_MAX, DISCOVER_FILTER_VALUES_MAX, DISCOVER_TEXT_MAX, } from '../../core/limits.js';
121
+ import { eachOnce, emptyStringToUndefined, multiValueQuery, objectIdSchema, optionalTrimmedString, paginationQuerySchema, } from '../../core/common.js';
122
+ import { COMMUNITY_BAN_REASON_MAX, COMMUNITY_DECLINE_REASON_MAX, COMMUNITY_DECLINE_REASON_MIN, COMMUNITY_DESCRIPTION_MAX, COMMUNITY_NAME_MAX, COMMUNITY_NAME_MIN, COMMUNITY_RULE_MAX, COMMUNITY_RULES_MAX, COMMUNITY_SUGGESTION_WHY_MAX, DAY_MS, DISCOVER_FILTER_VALUES_MAX, DISCOVER_TEXT_MAX, } from '../../core/limits.js';
121
123
  import { paginatedSchema } from '../../core/responses.js';
122
124
  import { VALIDATION_MESSAGE } from '../../core/validation.js';
123
125
  import { mediaImageSchema } from '../media/media.js';
@@ -133,7 +135,7 @@ export const COMMUNITY_SUGGESTIONS_OPEN_MAX = 3;
133
135
  * The shortest time between two notify-everyone announcements in one
134
136
  * community, so members are not spammed (`COMMUNITY_ANNOUNCE_TOO_SOON`).
135
137
  */
136
- export const COMMUNITY_ANNOUNCE_INTERVAL_MS = 24 * 60 * 60 * 1000;
138
+ export const COMMUNITY_ANNOUNCE_INTERVAL_MS = DAY_MS;
137
139
  // ─── Vocabulary ──────────────────────────────────────────────────────────────
138
140
  // ⚠ Every list below is STORED. Append only; removing a value orphans rows.
139
141
  /** See the module note's table. */
@@ -165,7 +167,22 @@ export const communityMemberStatusSchema = z.enum(COMMUNITY_MEMBER_STATUS_VALUES
165
167
  /** `archived`: read-only and out of Discover; members still read it. Staff only. */
166
168
  export const COMMUNITY_STATUS_VALUES = ['active', 'archived'];
167
169
  export const communityStatusSchema = z.enum(COMMUNITY_STATUS_VALUES);
168
- export const COMMUNITY_SUGGESTION_STATUS_VALUES = ['open', 'approved', 'declined'];
170
+ /**
171
+ * Whether a community may take type `to` now (0.18.0): ONE rule for the
172
+ * server's refusal (`COMMUNITY_ARCHIVED`) and the screen's choice. An
173
+ * archived community lets nobody new in, so it may be narrowed (private,
174
+ * hidden) but never opened to public, which would let its waiting requests in.
175
+ */
176
+ export function communityTypeChangeAllowed(status, to) {
177
+ return !(status === 'archived' && to === 'public');
178
+ }
179
+ /** How staff decided a suggestion (0.18.0: named, for the bell and the backend's model). */
180
+ export const COMMUNITY_SUGGESTION_DECISION_VALUES = ['approved', 'declined'];
181
+ export const communitySuggestionDecisionSchema = z.enum(COMMUNITY_SUGGESTION_DECISION_VALUES);
182
+ export const COMMUNITY_SUGGESTION_STATUS_VALUES = [
183
+ 'open',
184
+ ...COMMUNITY_SUGGESTION_DECISION_VALUES,
185
+ ];
169
186
  export const communitySuggestionStatusSchema = z.enum(COMMUNITY_SUGGESTION_STATUS_VALUES);
170
187
  // ─── Read shapes ─────────────────────────────────────────────────────────────
171
188
  /**
@@ -221,12 +238,25 @@ export const communityViewerSchema = communityCardViewerSchema.extend({
221
238
  canRequest: z.boolean(),
222
239
  /** Active member, community not archived: the composer. */
223
240
  canPost: z.boolean(),
224
- /** Active member who is not its last admin. */
241
+ /**
242
+ * Active member who is not its last admin, or the last admin of a community
243
+ * nobody else is in (0.18.0): their leaving ARCHIVES it, nothing deleted,
244
+ * since there is no one to hand it to. A last admin with members hands it
245
+ * over first (`COMMUNITY_LAST_ADMIN`).
246
+ */
225
247
  canLeave: z.boolean(),
248
+ /**
249
+ * Leaving ARCHIVES it (0.18.0): the viewer is its last admin and nobody else
250
+ * is in it, counted as leaving counts. The server's answer, so the dialog
251
+ * never guesses from a stored count.
252
+ */
253
+ leaveArchives: z.boolean(),
226
254
  /**
227
255
  * Moderators and admins (and managers, super admins): requests, invites,
228
- * pins, hiding, removing members. On an ARCHIVED community approving,
229
- * inviting, accepting and pinning answer `COMMUNITY_ARCHIVED`; declining,
256
+ * pins, hiding, removing members. On an ARCHIVED community nobody new comes
257
+ * in: approving, inviting, accepting, pinning AND opening it to public
258
+ * (which would let waiting requests in, `communityTypeChangeAllowed`,
259
+ * 0.18.0) answer `COMMUNITY_ARCHIVED`; narrowing its type, declining,
230
260
  * cancelling, removing, banning, roles and hiding still work.
231
261
  */
232
262
  canModerate: z.boolean(),
@@ -380,10 +410,7 @@ const descriptionSchema = z.string().trim().min(1).max(COMMUNITY_DESCRIPTION_MAX
380
410
  const rulesSchema = z
381
411
  .array(z.string().trim().min(1).max(COMMUNITY_RULE_MAX))
382
412
  .max(COMMUNITY_RULES_MAX);
383
- const topicsSchema = z
384
- .array(topicSchema)
385
- .max(COMMUNITY_TOPICS_MAX)
386
- .refine((topics) => new Set(topics).size === topics.length, {
413
+ const topicsSchema = z.array(topicSchema).max(COMMUNITY_TOPICS_MAX).refine(eachOnce, {
387
414
  error: VALIDATION_MESSAGE.topicsDuplicate,
388
415
  });
389
416
  /**
@@ -438,7 +465,8 @@ export const setCommunityMemberRoleBodySchema = z.object({ role: communityRoleSc
438
465
  /** `POST /communities/:id/bans` (admins): removes them if active, and keeps them out. */
439
466
  export const banCommunityMemberBodySchema = z.object({
440
467
  userId: objectIdSchema,
441
- reason: z.string().trim().min(1).max(COMMUNITY_BAN_REASON_MAX).optional(),
468
+ /** Why, for the record. Blank means no reason (0.18.0: a blank box was refused). */
469
+ reason: optionalTrimmedString(COMMUNITY_BAN_REASON_MAX),
442
470
  });
443
471
  /**
444
472
  * `POST /communities/:id/pins` (moderators): pin one of the community's posts
@@ -1 +1 @@
1
- {"version":3,"file":"communities.js","sourceRoot":"","sources":["../../../src/domains/communities/communities.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * founder-schema — Communities: official spaces inside Founder Circle (0.9.0)\n *\n * THE USER'S DECISIONS (2026-10-08), each asked on its own:\n *\n * - OFFICIAL: managers, super admins, and members given the\n * `create_communities` capability create them. Everyone else SUGGESTS one;\n * managers and super admins review the suggestions.\n * - THREE TYPES, three separate questions answered per type:\n *\n * public private hidden\n * listed in Discover yes yes no\n * header (name, about, signed-in signed-in members and\n * rules, admins, count) members members invitees (404 otherwise)\n * posts, polls, members signed-in members only members only\n * joining one tap request, then invite only,\n * approval then accept\n *\n * Taking part (post, poll, comment, react, vote, save, report) is for\n * members of every type. \"Members\" means ACTIVE members: someone who\n * requested, was invited or is banned is a non-member for every rule.\n * - PUBLIC MEANS PUBLIC INSIDE FOUNDER CIRCLE: a signed-out visitor sees no\n * community content of any type, even by a shared link.\n * - THE HOME FEED adds only the communities the member joined.\n * - NO CHAT IN 0.9.0 (feed-first). Announcements are pinned posts\n * (`COMMUNITY_PINS_MAX`), optionally notifying every member.\n *\n * A banned member sees the community as hidden (404 everywhere) until\n * unbanned. Platform staff acting as moderator, manager or super admin READ\n * every community, as they read every post, and moderate its content through\n * the staff moderation queue; to take part they join like anyone else.\n *\n * Refusals follow what the caller can SEE: 404 for something they may not\n * see (the same as for something that does not exist, so nothing is\n * probed), 403 `COMMUNITY_JOIN_REQUIRED` for something they see but must join\n * to read or to take part in.\n *\n * Content in a community carries no product and no ask, and cannot be\n * reposted (a repost is general content, readable signed out): two leak paths\n * closed by construction. Design: founder-circle-backend `docs/communities.md`.\n *\n * Inside a community:\n *\n * member moderator admin manager,\n * super admin\n * post, poll, comment, react, vote ✓ ✓ ✓ ✓ (a member)\n * approve requests, invite, pin, hide ✓ ✓ ✓\n * remove a member (not a moderator) ✓ ✓ ✓\n * remove a moderator ✓ ✓\n * remove or ban an admin ✓\n * notify all, ban, roles, edit, type ✓ ✓\n * archive, delete ✓\n *\n * An admin may unmake another admin (then act on them as on a member). Each\n * member row says what this viewer may do to it (`communityMemberSchema.viewer`):\n * a client never works it out from roles.\n *\n * A community always keeps an admin while anyone can be one\n * (`COMMUNITY_LAST_ADMIN`): an admin leaves, steps down, or deletes their\n * account only once someone else is admin (the user's rule, 2026-10-08). When\n * nobody else is active, or the account was deleted where it cannot be\n * refused (central sign-in), the community is ORPHANED: managers and super\n * admins run it (they can act on any community), it is flagged in the audit\n * log (`community.orphaned`), and the page says so to them (`orphaned`).\n *\n * Routes (all signed in):\n * GET /api/v1/communities communityDiscoverQuerySchema -> communityCardPageSchema\n * GET /api/v1/communities/mine paginationQuerySchema -> communityCardPageSchema\n * GET /api/v1/communities/invites communityInvitesSchema (mine, waiting)\n * GET /api/v1/communities/orphaned paginationQuerySchema -> communityCardPageSchema\n * (managers, super admins: communities left with no admin, newest first)\n * POST /api/v1/communities createCommunityBodySchema -> IdResponse\n * GET /api/v1/communities/:communityId communitySchema\n * PATCH /api/v1/communities/:communityId updateCommunityBodySchema -> communitySchema\n * PUT /api/v1/communities/:communityId/icon setCommunityIconBodySchema -> communitySchema\n * DELETE /api/v1/communities/:communityId/icon -> communitySchema\n * PUT /api/v1/communities/:communityId/visibility setCommunityVisibilityBodySchema -> communitySchema\n * PUT /api/v1/communities/:communityId/status setCommunityStatusBodySchema -> communitySchema (staff)\n * DELETE /api/v1/communities/:communityId -> IdResponse (staff)\n * GET /api/v1/communities/:communityId/feed paginationQuerySchema -> FeedPage (newest first;\n * pinned items are in it too, in their place)\n * GET /api/v1/communities/:communityId/pinned PinnedItems (feed)\n * POST /api/v1/communities/:communityId/pins pinCommunityContentBodySchema -> PinnedItems\n * DELETE /api/v1/communities/:communityId/pins/:contentId -> PinnedItems\n * POST /api/v1/communities/:communityId/join -> communitySchema (public: joined; private: requested)\n * DELETE /api/v1/communities/:communityId/join cancel a request -> communitySchema\n * POST /api/v1/communities/:communityId/leave -> IdResponse\n * GET /api/v1/communities/:communityId/members communityMembersQuerySchema -> communityMemberPageSchema\n * GET /api/v1/communities/:communityId/requests paginationQuerySchema -> communityRequestPageSchema\n * PUT /api/v1/communities/:communityId/requests/:userId approve -> IdResponse\n * DELETE /api/v1/communities/:communityId/requests/:userId decline -> IdResponse\n * GET /api/v1/communities/:communityId/invites paginationQuerySchema -> communityPendingInvitePageSchema\n * POST /api/v1/communities/:communityId/invites inviteCommunityMemberBodySchema -> communityPendingInviteSchema\n * DELETE /api/v1/communities/:communityId/invites/:userId cancel -> IdResponse\n * PUT /api/v1/communities/:communityId/invite accept (the invitee) -> communitySchema\n * DELETE /api/v1/communities/:communityId/invite decline (the invitee) -> IdResponse\n * PUT /api/v1/communities/:communityId/members/:userId/role setCommunityMemberRoleBodySchema -> IdResponse\n * DELETE /api/v1/communities/:communityId/members/:userId remove -> IdResponse\n * GET /api/v1/communities/:communityId/bans paginationQuerySchema -> communityBanPageSchema\n * POST /api/v1/communities/:communityId/bans banCommunityMemberBodySchema -> IdResponse\n * DELETE /api/v1/communities/:communityId/bans/:userId unban -> IdResponse\n * PUT /api/v1/communities/:communityId/content/:contentId/hidden hide in the community -> IdResponse\n * DELETE /api/v1/communities/:communityId/content/:contentId/hidden restore -> IdResponse\n * PUT /api/v1/communities/:communityId/comments/:commentId/hidden hide a comment in it -> IdResponse\n * DELETE /api/v1/communities/:communityId/comments/:commentId/hidden restore -> IdResponse\n * GET /api/v1/communities/:communityId/hidden paginationQuerySchema -> FeedPage (moderators:\n * what ITS moderators hid, newest first; a staff hide is staff's to undo and is not listed)\n * GET /api/v1/communities/:communityId/hidden/comments paginationQuerySchema -> commentPageSchema\n * POST /api/v1/community-suggestions createCommunitySuggestionBodySchema -> communitySuggestionSchema\n * GET /api/v1/community-suggestions/mine paginationQuerySchema -> communitySuggestionPageSchema\n * GET /api/v1/community-suggestions communitySuggestionsQuerySchema -> communitySuggestionPageSchema (staff)\n * POST /api/v1/community-suggestions/:suggestionId/approve createCommunityBodySchema -> IdResponse (the community)\n * POST /api/v1/community-suggestions/:suggestionId/decline declineCommunitySuggestionBodySchema -> communitySuggestionSchema\n * (posting into a community: `communityId` on the feed's create bodies)\n *\n * @module founder-schema/domains/communities\n */\n\nimport { z } from 'zod';\nimport {\n emptyStringToUndefined,\n multiValueQuery,\n objectIdSchema,\n optionalTrimmedString,\n paginationQuerySchema,\n} from '../../core/common.js';\nimport {\n COMMUNITY_BAN_REASON_MAX,\n COMMUNITY_DECLINE_REASON_MAX,\n COMMUNITY_DECLINE_REASON_MIN,\n COMMUNITY_DESCRIPTION_MAX,\n COMMUNITY_NAME_MAX,\n COMMUNITY_NAME_MIN,\n COMMUNITY_RULE_MAX,\n COMMUNITY_RULES_MAX,\n COMMUNITY_SUGGESTION_WHY_MAX,\n DISCOVER_FILTER_VALUES_MAX,\n DISCOVER_TEXT_MAX,\n} from '../../core/limits.js';\nimport { paginatedSchema } from '../../core/responses.js';\nimport { VALIDATION_MESSAGE } from '../../core/validation.js';\nimport { mediaImageSchema } from '../media/media.js';\nimport { topicSchema } from '../onboarding/onboarding.js';\nimport { memberBylineSchema } from '../profile/founder-profile.js';\n\n/** Topics a community carries: what Discover filters by. */\nexport const COMMUNITY_TOPICS_MAX = 3;\n/** Announcements pinned to the top of one community at once. */\nexport const COMMUNITY_PINS_MAX = 3;\n/** Suggestions one member may have waiting for review at once. */\nexport const COMMUNITY_SUGGESTIONS_OPEN_MAX = 3;\n/**\n * The shortest time between two notify-everyone announcements in one\n * community, so members are not spammed (`COMMUNITY_ANNOUNCE_TOO_SOON`).\n */\nexport const COMMUNITY_ANNOUNCE_INTERVAL_MS = 24 * 60 * 60 * 1000;\n\n// ─── Vocabulary ──────────────────────────────────────────────────────────────\n// ⚠ Every list below is STORED. Append only; removing a value orphans rows.\n\n/** See the module note's table. */\nexport const COMMUNITY_VISIBILITY_VALUES = ['public', 'private', 'hidden'] as const;\nexport const communityVisibilitySchema = z.enum(COMMUNITY_VISIBILITY_VALUES);\nexport type CommunityVisibility = z.infer<typeof communityVisibilitySchema>;\n\n/**\n * How private each type is, least first. A change to a LOWER rank exposes what\n * was already posted, so it needs `confirmExposure` (and is audited).\n */\nexport const COMMUNITY_VISIBILITY_RANK = {\n public: 0,\n private: 1,\n hidden: 2,\n} as const satisfies Record<CommunityVisibility, number>;\n\n/** Whether moving from one type to another exposes what was already there. */\nexport function communityChangeExposes(\n from: CommunityVisibility,\n to: CommunityVisibility,\n): boolean {\n return COMMUNITY_VISIBILITY_RANK[to] < COMMUNITY_VISIBILITY_RANK[from];\n}\n\n/** A member's role inside one community. */\nexport const COMMUNITY_ROLE_VALUES = ['admin', 'moderator', 'member'] as const;\nexport const communityRoleSchema = z.enum(COMMUNITY_ROLE_VALUES);\nexport type CommunityRole = z.infer<typeof communityRoleSchema>;\n\n/**\n * Where someone stands with one community. `requested` (private: waiting for\n * approval), `invited` (waiting for their answer), `banned` (the community is\n * hidden from them). Leaving or being removed deletes the row.\n */\nexport const COMMUNITY_MEMBER_STATUS_VALUES = ['active', 'requested', 'invited', 'banned'] as const;\nexport const communityMemberStatusSchema = z.enum(COMMUNITY_MEMBER_STATUS_VALUES);\nexport type CommunityMemberStatus = z.infer<typeof communityMemberStatusSchema>;\n\n/** `archived`: read-only and out of Discover; members still read it. Staff only. */\nexport const COMMUNITY_STATUS_VALUES = ['active', 'archived'] as const;\nexport const communityStatusSchema = z.enum(COMMUNITY_STATUS_VALUES);\nexport type CommunityStatus = z.infer<typeof communityStatusSchema>;\n\nexport const COMMUNITY_SUGGESTION_STATUS_VALUES = ['open', 'approved', 'declined'] as const;\nexport const communitySuggestionStatusSchema = z.enum(COMMUNITY_SUGGESTION_STATUS_VALUES);\nexport type CommunitySuggestionStatus = z.infer<typeof communitySuggestionStatusSchema>;\n\n// ─── Read shapes ─────────────────────────────────────────────────────────────\n\n/**\n * A community named on something else: \"in AI Builders\" on a post or poll, a\n * notification. `iconUrl` is the icon's smallest size.\n */\nexport const communityChipSchema = z.object({\n id: objectIdSchema,\n /** For a readable URL, `/communities/<id>/<slug>`. The id resolves; a renamed community keeps its links. */\n slug: z.string(),\n name: z.string(),\n iconUrl: z.url().optional(),\n visibility: communityVisibilitySchema,\n /** Present (true) once it is archived: read only, nobody takes part. */\n archived: z.boolean().optional(),\n});\nexport type CommunityChip = z.infer<typeof communityChipSchema>;\n\n/** Where THIS viewer stands with a community, on a card. Banned viewers never see it. */\nexport const communityCardViewerSchema = z.object({\n /** Null: not a member and nothing pending. Never `banned` (they get 404). */\n status: communityMemberStatusSchema.exclude(['banned']).nullable(),\n /** Their role while active, else null. */\n role: communityRoleSchema.nullable(),\n});\nexport type CommunityCardViewer = z.infer<typeof communityCardViewerSchema>;\n\n/** A community on Discover and in \"your communities\". */\nexport const communityCardSchema = z.object({\n id: objectIdSchema,\n slug: z.string(),\n name: z.string(),\n description: z.string(),\n icon: mediaImageSchema.optional(),\n visibility: communityVisibilitySchema,\n status: communityStatusSchema,\n topics: z.array(topicSchema).max(COMMUNITY_TOPICS_MAX),\n /** Active members. */\n memberCount: z.number().int().nonnegative(),\n /** Visible posts and polls in it. */\n postCount: z.number().int().nonnegative(),\n viewer: communityCardViewerSchema.optional(),\n});\nexport type CommunityCard = z.infer<typeof communityCardSchema>;\n\n/**\n * What THIS viewer may do on the community page, decided by the server and\n * sent as plain answers (the rule of `viewerStateSchema` on a post): a client\n * never derives a power from `role`.\n */\nexport const communityViewerSchema = communityCardViewerSchema.extend({\n /** Read its posts, polls and comments now. False on a private one before joining. */\n canRead: z.boolean(),\n /** Read its member list. */\n canSeeMembers: z.boolean(),\n /** Public, active, and the viewer has no row (nothing pending): offer Join. */\n canJoin: z.boolean(),\n /** Private, active, and the viewer has no row: offer Request to join. */\n canRequest: z.boolean(),\n /** Active member, community not archived: the composer. */\n canPost: z.boolean(),\n /** Active member who is not its last admin. */\n canLeave: z.boolean(),\n /**\n * Moderators and admins (and managers, super admins): requests, invites,\n * pins, hiding, removing members. On an ARCHIVED community approving,\n * inviting, accepting and pinning answer `COMMUNITY_ARCHIVED`; declining,\n * cancelling, removing, banning, roles and hiding still work.\n */\n canModerate: z.boolean(),\n /** Admins (and managers, super admins): details, icon, type, roles, bans. */\n canManage: z.boolean(),\n /**\n * Change members' roles (hand it over) and lift bans (0.13.0): every admin,\n * INCLUDING one whose membership ended and so cannot manage or moderate any\n * more. They keep this so a sole admin is never trapped: Manage shows them\n * Members (roles only) and Bans (unban only).\n */\n canAssign: z.boolean(),\n /** May notify every member with an announcement now (admins, at most once per `COMMUNITY_ANNOUNCE_INTERVAL_MS`). */\n canAnnounce: z.boolean(),\n /** Managers and super admins: archive, restore, delete. */\n canArchive: z.boolean(),\n});\nexport type CommunityViewer = z.infer<typeof communityViewerSchema>;\n\n/**\n * One person in a community, live-joined like every byline. In the member\n * list, admins first, then moderators, then members, each by when they joined.\n * `viewer` (0.9.0, on the member list only) is what THIS viewer may do to\n * them, the server's own rules (who outranks whom, never oneself, never the\n * last admin).\n */\nexport const communityMemberSchema = memberBylineSchema.extend({\n role: communityRoleSchema,\n joinedAt: z.iso.datetime(),\n viewer: z\n .object({\n canSetRole: z.boolean(),\n canRemove: z.boolean(),\n canBan: z.boolean(),\n })\n .optional(),\n});\nexport type CommunityMember = z.infer<typeof communityMemberSchema>;\n\n/** The community page. The header is what a non-member of a private one may see too. */\nexport const communitySchema = communityCardSchema.extend({\n rules: z.array(z.string()).max(COMMUNITY_RULES_MAX),\n /**\n * Its admins and moderators, admins first, by when they joined: who to ask.\n * EMPTY for a viewer who may not read it (a private community before\n * joining, a hidden one's invitee): who is in it is its members' to see.\n */\n team: z.array(communityMemberSchema),\n createdAt: z.iso.datetime(),\n updatedAt: z.iso.datetime(),\n archivedAt: z.iso.datetime().nullable(),\n /**\n * Only for managers and super admins: it has no admin left (its last one's\n * account was deleted where that cannot be refused), so staff run it until\n * they make a member admin, which clears it.\n */\n orphaned: z.boolean().optional(),\n viewer: communityViewerSchema.optional(),\n});\nexport type Community = z.infer<typeof communitySchema>;\n\n/** A request to join a private community, as its moderators see it. */\nexport const communityRequestSchema = z.object({\n member: memberBylineSchema,\n requestedAt: z.iso.datetime(),\n});\nexport type CommunityRequest = z.infer<typeof communityRequestSchema>;\n\n/** An invitation nobody has answered yet, as its moderators see it. */\nexport const communityPendingInviteSchema = z.object({\n member: memberBylineSchema,\n /** Null when whoever invited has since deleted their account. */\n invitedBy: memberBylineSchema.nullable(),\n invitedAt: z.iso.datetime(),\n});\nexport type CommunityPendingInvite = z.infer<typeof communityPendingInviteSchema>;\n\n/** An invitation waiting for the viewer's answer. */\nexport const communityInviteSchema = z.object({\n community: communityChipSchema.extend({ description: z.string() }),\n invitedBy: memberBylineSchema.nullable(),\n invitedAt: z.iso.datetime(),\n});\nexport type CommunityInvite = z.infer<typeof communityInviteSchema>;\n\n/** `GET /communities/invites`. Never paged: invitations are few, and each needs an answer. */\nexport const communityInvitesSchema = z.object({ items: z.array(communityInviteSchema) });\nexport type CommunityInvites = z.infer<typeof communityInvitesSchema>;\n\n/** Someone banned from a community, as its admins see it. */\nexport const communityBanSchema = z.object({\n member: memberBylineSchema,\n bannedBy: memberBylineSchema.nullable(),\n bannedAt: z.iso.datetime(),\n /** For the admins' own record; never shown to the banned member. */\n reason: z.string().max(COMMUNITY_BAN_REASON_MAX).optional(),\n});\nexport type CommunityBan = z.infer<typeof communityBanSchema>;\n\n/** A suggestion, as its author and the reviewers see it. */\nexport const communitySuggestionSchema = z.object({\n id: objectIdSchema,\n /** Null when its author has since deleted their account. */\n suggestedBy: memberBylineSchema.nullable(),\n name: z.string(),\n description: z.string(),\n why: z.string().optional(),\n visibility: communityVisibilitySchema,\n topics: z.array(topicSchema).max(COMMUNITY_TOPICS_MAX),\n status: communitySuggestionStatusSchema,\n decidedBy: memberBylineSchema.nullable(),\n decidedAt: z.iso.datetime().nullable(),\n /** Why it was declined, shown to its author. */\n declineReason: z.string().optional(),\n /**\n * The community it became, once approved. Absent if that community is since\n * deleted, or the viewer may no longer see it (banned from a hidden one).\n */\n community: communityChipSchema.optional(),\n createdAt: z.iso.datetime(),\n});\nexport type CommunitySuggestion = z.infer<typeof communitySuggestionSchema>;\n\nexport const communityCardPageSchema = paginatedSchema(communityCardSchema);\nexport type CommunityCardPage = z.infer<typeof communityCardPageSchema>;\nexport const communityMemberPageSchema = paginatedSchema(communityMemberSchema);\nexport type CommunityMemberPage = z.infer<typeof communityMemberPageSchema>;\nexport const communityRequestPageSchema = paginatedSchema(communityRequestSchema);\nexport type CommunityRequestPage = z.infer<typeof communityRequestPageSchema>;\nexport const communityPendingInvitePageSchema = paginatedSchema(communityPendingInviteSchema);\nexport type CommunityPendingInvitePage = z.infer<typeof communityPendingInvitePageSchema>;\nexport const communityBanPageSchema = paginatedSchema(communityBanSchema);\nexport type CommunityBanPage = z.infer<typeof communityBanPageSchema>;\nexport const communitySuggestionPageSchema = paginatedSchema(communitySuggestionSchema);\nexport type CommunitySuggestionPage = z.infer<typeof communitySuggestionPageSchema>;\n\n// ─── Queries and params ──────────────────────────────────────────────────────\n\n/**\n * `GET /communities`: public and private communities that are not archived\n * (hidden ones never), most members first. `q` matches the start of the\n * name; an emptied box (`?q=`) is no search, never a 400. `topic` means \"any of\".\n */\nexport const communityDiscoverQuerySchema = paginationQuerySchema.extend({\n q: optionalTrimmedString(DISCOVER_TEXT_MAX),\n topic: multiValueQuery(topicSchema, DISCOVER_FILTER_VALUES_MAX),\n});\nexport type CommunityDiscoverQuery = z.infer<typeof communityDiscoverQuerySchema>;\nexport type CommunityDiscoverQueryInput = z.input<typeof communityDiscoverQuerySchema>;\n\n/** `GET /communities/:id/members`: everyone, or one role (`?role=admin`). */\nexport const communityMembersQuerySchema = paginationQuerySchema.extend({\n role: z.preprocess(emptyStringToUndefined, communityRoleSchema.optional()),\n});\nexport type CommunityMembersQuery = z.infer<typeof communityMembersQuerySchema>;\nexport type CommunityMembersQueryInput = z.input<typeof communityMembersQuerySchema>;\n\n/** `GET /community-suggestions` (staff): waiting ones by default, oldest first. */\nexport const communitySuggestionsQuerySchema = paginationQuerySchema.extend({\n status: z.preprocess(emptyStringToUndefined, communitySuggestionStatusSchema.default('open')),\n});\nexport type CommunitySuggestionsQuery = z.infer<typeof communitySuggestionsQuerySchema>;\nexport type CommunitySuggestionsQueryInput = z.input<typeof communitySuggestionsQuerySchema>;\n\nexport const communityParamsSchema = z.object({ communityId: objectIdSchema });\nexport type CommunityParams = z.infer<typeof communityParamsSchema>;\n/** `/communities/:communityId/{members,requests,invites,bans}/:userId`. */\nexport const communityMemberParamsSchema = z.object({\n communityId: objectIdSchema,\n userId: objectIdSchema,\n});\nexport type CommunityMemberParams = z.infer<typeof communityMemberParamsSchema>;\n/** `/communities/:communityId/{pins,content}/:contentId`. */\nexport const communityContentParamsSchema = z.object({\n communityId: objectIdSchema,\n contentId: objectIdSchema,\n});\nexport type CommunityContentParams = z.infer<typeof communityContentParamsSchema>;\n/** `/communities/:communityId/comments/:commentId/hidden` (0.9.0). */\nexport const communityCommentParamsSchema = z.object({\n communityId: objectIdSchema,\n commentId: objectIdSchema,\n});\nexport type CommunityCommentParams = z.infer<typeof communityCommentParamsSchema>;\nexport const communitySuggestionParamsSchema = z.object({ suggestionId: objectIdSchema });\nexport type CommunitySuggestionParams = z.infer<typeof communitySuggestionParamsSchema>;\n\n// ─── Write bodies ────────────────────────────────────────────────────────────\n// Each its own object with NO defaults (see `updateFounderProfileBodySchema`).\n\nconst nameSchema = z.string().trim().min(COMMUNITY_NAME_MIN).max(COMMUNITY_NAME_MAX);\nconst descriptionSchema = z.string().trim().min(1).max(COMMUNITY_DESCRIPTION_MAX);\nconst rulesSchema = z\n .array(z.string().trim().min(1).max(COMMUNITY_RULE_MAX))\n .max(COMMUNITY_RULES_MAX);\nconst topicsSchema = z\n .array(topicSchema)\n .max(COMMUNITY_TOPICS_MAX)\n .refine((topics) => new Set(topics).size === topics.length, {\n error: VALIDATION_MESSAGE.topicsDuplicate,\n });\n\n/**\n * `POST /communities` (managers, super admins and capability holders), and\n * the reviewer's edited version when approving a suggestion. The creator\n * becomes its first admin. A name a live PUBLIC or PRIVATE community has is\n * `COMMUNITY_NAME_TAKEN` (letter case ignored, runs of spaces read as one);\n * hidden communities' names are never compared, so no name probes for one.\n * Approving a private or hidden one invites its suggester. The icon is a\n * processed `community_icon` upload.\n */\nexport const createCommunityBodySchema = z.object({\n name: nameSchema,\n description: descriptionSchema,\n visibility: communityVisibilitySchema,\n rules: rulesSchema.optional(),\n topics: topicsSchema.optional(),\n iconMediaId: objectIdSchema.optional(),\n});\nexport type CreateCommunityBody = z.infer<typeof createCommunityBodySchema>;\n\n/** `PATCH /communities/:id` (admins): only the keys that changed. Type and icon have their own routes. */\nexport const updateCommunityBodySchema = z.object({\n name: nameSchema.optional(),\n description: descriptionSchema.optional(),\n /** Sent whole; empty clears them. */\n rules: rulesSchema.optional(),\n topics: topicsSchema.optional(),\n});\nexport type UpdateCommunityBody = z.infer<typeof updateCommunityBodySchema>;\n\n/** `PUT /communities/:id/icon`: a processed `community_icon` upload. The old icon's files are deleted. */\nexport const setCommunityIconBodySchema = z.object({ mediaId: objectIdSchema });\nexport type SetCommunityIconBody = z.infer<typeof setCommunityIconBodySchema>;\n\n/**\n * `PUT /communities/:id/visibility` (admins). A change that exposes what was\n * already posted (`communityChangeExposes`: toward public, or hidden to\n * private) needs `confirmExposure: true`, else `COMMUNITY_EXPOSURE_UNCONFIRMED`:\n * the web asks first, and a client cannot skip the question. Audited.\n */\nexport const setCommunityVisibilityBodySchema = z.object({\n visibility: communityVisibilitySchema,\n confirmExposure: z.boolean().optional(),\n});\nexport type SetCommunityVisibilityBody = z.infer<typeof setCommunityVisibilityBodySchema>;\n\n/** `PUT /communities/:id/status` (staff). Audited. */\nexport const setCommunityStatusBodySchema = z.object({ status: communityStatusSchema });\nexport type SetCommunityStatusBody = z.infer<typeof setCommunityStatusBodySchema>;\n\n/**\n * `POST /communities/:id/invites` (moderators, private and hidden only;\n * a public community needs none: `COMMUNITY_INVITE_NOT_NEEDED`). Someone who\n * cannot join (not onboarded, paused, suspended, deleted) is\n * `COMMUNITY_MEMBER_NOT_INVITABLE`; banned, `COMMUNITY_MEMBER_BANNED`; already\n * a member, requested or invited, `COMMUNITY_ALREADY_MEMBER`.\n */\nexport const inviteCommunityMemberBodySchema = z.object({ userId: objectIdSchema });\nexport type InviteCommunityMemberBody = z.infer<typeof inviteCommunityMemberBodySchema>;\n\n/** `PUT /communities/:id/members/:userId/role` (admins). Never the last admin's own step down. */\nexport const setCommunityMemberRoleBodySchema = z.object({ role: communityRoleSchema });\nexport type SetCommunityMemberRoleBody = z.infer<typeof setCommunityMemberRoleBodySchema>;\n\n/** `POST /communities/:id/bans` (admins): removes them if active, and keeps them out. */\nexport const banCommunityMemberBodySchema = z.object({\n userId: objectIdSchema,\n reason: z.string().trim().min(1).max(COMMUNITY_BAN_REASON_MAX).optional(),\n});\nexport type BanCommunityMemberBody = z.infer<typeof banCommunityMemberBodySchema>;\n\n/**\n * `POST /communities/:id/pins` (moderators): pin one of the community's posts\n * or polls as an announcement (`COMMUNITY_PINS_FULL` past `COMMUNITY_PINS_MAX`).\n * `notifyMembers` (admins only) rings every active member's bell, at most once\n * per `COMMUNITY_ANNOUNCE_INTERVAL_MS` (`COMMUNITY_ANNOUNCE_TOO_SOON`).\n */\nexport const pinCommunityContentBodySchema = z.object({\n contentId: objectIdSchema,\n notifyMembers: z.boolean(),\n});\nexport type PinCommunityContentBody = z.infer<typeof pinCommunityContentBodySchema>;\n\n/**\n * `POST /community-suggestions`: any onboarded member, at most\n * `COMMUNITY_SUGGESTIONS_OPEN_MAX` waiting at once (`COMMUNITY_SUGGESTIONS_FULL`).\n */\nexport const createCommunitySuggestionBodySchema = z.object({\n name: nameSchema,\n description: descriptionSchema,\n why: z.string().trim().min(1).max(COMMUNITY_SUGGESTION_WHY_MAX).optional(),\n visibility: communityVisibilitySchema,\n topics: topicsSchema.optional(),\n});\nexport type CreateCommunitySuggestionBody = z.infer<typeof createCommunitySuggestionBodySchema>;\n\n/**\n * `POST /community-suggestions/:id/decline` (staff): the reason is shown to the\n * suggester. A decided suggestion is `COMMUNITY_SUGGESTION_DECIDED`.\n */\nexport const declineCommunitySuggestionBodySchema = z.object({\n reason: z.string().trim().min(COMMUNITY_DECLINE_REASON_MIN).max(COMMUNITY_DECLINE_REASON_MAX),\n});\nexport type DeclineCommunitySuggestionBody = z.infer<typeof declineCommunitySuggestionBodySchema>;\n"]}
1
+ {"version":3,"file":"communities.js","sourceRoot":"","sources":["../../../src/domains/communities/communities.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * founder-schema — Communities: official spaces inside Founder Circle (0.9.0)\n *\n * THE USER'S DECISIONS (2026-10-08), each asked on its own:\n *\n * - OFFICIAL: managers, super admins, and members given the\n * `create_communities` capability create them. Everyone else SUGGESTS one;\n * managers and super admins review the suggestions.\n * - THREE TYPES, three separate questions answered per type:\n *\n * public private hidden\n * listed in Discover yes yes no\n * header (name, about, signed-in signed-in members and\n * rules, admins, count) members members invitees (404 otherwise)\n * posts, polls, members signed-in members only members only\n * joining one tap request, then invite only,\n * approval then accept\n *\n * Taking part (post, poll, comment, react, vote, save) is for members of\n * every type. \"Members\" means ACTIVE members: someone who requested, was\n * invited or is banned is a non-member for every rule. Taking a reaction,\n * a vote or a save BACK needs only read access, and reporting is open to\n * any signed-in reader (safety, 0.13.0).\n * - PUBLIC MEANS PUBLIC INSIDE FOUNDER CIRCLE: a signed-out visitor sees no\n * community content of any type, even by a shared link.\n * - THE HOME FEED adds only the communities the member joined.\n * - NO CHAT IN 0.9.0 (feed-first). Announcements are pinned posts\n * (`COMMUNITY_PINS_MAX`), optionally notifying every member.\n *\n * A banned member sees the community as hidden (404 everywhere) until\n * unbanned. Platform staff acting as moderator, manager or super admin READ\n * every community, as they read every post, and moderate its content through\n * the staff moderation queue; to take part they join like anyone else.\n *\n * Refusals follow what the caller can SEE: 404 for something they may not\n * see (the same as for something that does not exist, so nothing is\n * probed), 403 `COMMUNITY_JOIN_REQUIRED` for something they see but must join\n * to read or to take part in.\n *\n * Content in a community carries no product and no ask, and cannot be\n * reposted (a repost is general content, readable signed out): two leak paths\n * closed by construction. Design: founder-circle-backend `docs/communities.md`.\n *\n * Inside a community:\n *\n * member moderator admin manager,\n * super admin\n * post, poll, comment, react, vote ✓ ✓ ✓ ✓ (a member)\n * approve requests, invite, pin, hide ✓ ✓ ✓\n * remove a member (not a moderator) ✓ ✓ ✓\n * remove a moderator ✓ ✓\n * remove or ban an admin ✓\n * notify all, ban, roles, edit, type ✓ ✓\n * archive, delete ✓\n *\n * An admin may unmake another admin (then act on them as on a member). Each\n * member row says what this viewer may do to it (`communityMemberSchema.viewer`):\n * a client never works it out from roles.\n *\n * A community always keeps an admin while anyone can be one\n * (`COMMUNITY_LAST_ADMIN`): an admin leaves, steps down, or deletes their\n * account only once someone else is admin (the user's rule, 2026-10-08). When\n * nobody else is active, or the account was deleted where it cannot be\n * refused (central sign-in), the community is ORPHANED: managers and super\n * admins run it (they can act on any community), it is flagged in the audit\n * log (`community.orphaned`), and the page says so to them (`orphaned`).\n *\n * Routes (all signed in):\n * GET /api/v1/communities communityDiscoverQuerySchema -> communityCardPageSchema\n * GET /api/v1/communities/mine paginationQuerySchema -> communityCardPageSchema\n * GET /api/v1/communities/invites communityInvitesSchema (mine, waiting)\n * GET /api/v1/communities/orphaned paginationQuerySchema -> communityCardPageSchema\n * (managers, super admins: communities left with no admin, newest first)\n * POST /api/v1/communities createCommunityBodySchema -> IdResponse\n * GET /api/v1/communities/:communityId communitySchema\n * PATCH /api/v1/communities/:communityId updateCommunityBodySchema -> communitySchema\n * PUT /api/v1/communities/:communityId/icon setCommunityIconBodySchema -> communitySchema\n * DELETE /api/v1/communities/:communityId/icon -> communitySchema\n * PUT /api/v1/communities/:communityId/visibility setCommunityVisibilityBodySchema -> communitySchema\n * PUT /api/v1/communities/:communityId/status setCommunityStatusBodySchema -> communitySchema (staff)\n * DELETE /api/v1/communities/:communityId -> IdResponse (staff)\n * GET /api/v1/communities/:communityId/feed paginationQuerySchema -> FeedPage (newest first;\n * pinned items are in it too, in their place)\n * GET /api/v1/communities/:communityId/pinned PinnedItems (feed)\n * POST /api/v1/communities/:communityId/pins pinCommunityContentBodySchema -> PinnedItems\n * DELETE /api/v1/communities/:communityId/pins/:contentId -> PinnedItems\n * POST /api/v1/communities/:communityId/join -> communitySchema (public: joined; private: requested)\n * DELETE /api/v1/communities/:communityId/join cancel a request -> communitySchema\n * POST /api/v1/communities/:communityId/leave -> IdResponse\n * GET /api/v1/communities/:communityId/members communityMembersQuerySchema -> communityMemberPageSchema\n * GET /api/v1/communities/:communityId/requests paginationQuerySchema -> communityRequestPageSchema\n * PUT /api/v1/communities/:communityId/requests/:userId approve -> IdResponse\n * DELETE /api/v1/communities/:communityId/requests/:userId decline -> IdResponse\n * GET /api/v1/communities/:communityId/invites paginationQuerySchema -> communityPendingInvitePageSchema\n * POST /api/v1/communities/:communityId/invites inviteCommunityMemberBodySchema -> communityPendingInviteSchema\n * DELETE /api/v1/communities/:communityId/invites/:userId cancel -> IdResponse\n * PUT /api/v1/communities/:communityId/invite accept (the invitee) -> communitySchema\n * DELETE /api/v1/communities/:communityId/invite decline (the invitee) -> IdResponse\n * PUT /api/v1/communities/:communityId/members/:userId/role setCommunityMemberRoleBodySchema -> IdResponse\n * DELETE /api/v1/communities/:communityId/members/:userId remove -> IdResponse\n * GET /api/v1/communities/:communityId/bans paginationQuerySchema -> communityBanPageSchema\n * POST /api/v1/communities/:communityId/bans banCommunityMemberBodySchema -> IdResponse\n * DELETE /api/v1/communities/:communityId/bans/:userId unban -> IdResponse\n * PUT /api/v1/communities/:communityId/content/:contentId/hidden hide in the community -> IdResponse\n * DELETE /api/v1/communities/:communityId/content/:contentId/hidden restore -> IdResponse\n * PUT /api/v1/communities/:communityId/comments/:commentId/hidden hide a comment in it -> IdResponse\n * DELETE /api/v1/communities/:communityId/comments/:commentId/hidden restore -> IdResponse\n * GET /api/v1/communities/:communityId/hidden paginationQuerySchema -> FeedPage (moderators:\n * what ITS moderators hid, newest first; a staff hide is staff's to undo and is not listed)\n * GET /api/v1/communities/:communityId/hidden/comments paginationQuerySchema -> commentPageSchema\n * POST /api/v1/community-suggestions createCommunitySuggestionBodySchema -> communitySuggestionSchema\n * GET /api/v1/community-suggestions/mine paginationQuerySchema -> communitySuggestionPageSchema\n * GET /api/v1/community-suggestions communitySuggestionsQuerySchema -> communitySuggestionPageSchema (staff)\n * POST /api/v1/community-suggestions/:suggestionId/approve createCommunityBodySchema -> IdResponse (the community)\n * POST /api/v1/community-suggestions/:suggestionId/decline declineCommunitySuggestionBodySchema -> communitySuggestionSchema\n * (posting into a community: `communityId` on the feed's create bodies)\n *\n * @module founder-schema/domains/communities\n */\n\nimport { z } from 'zod';\nimport {\n eachOnce,\n emptyStringToUndefined,\n multiValueQuery,\n objectIdSchema,\n optionalTrimmedString,\n paginationQuerySchema,\n} from '../../core/common.js';\nimport {\n COMMUNITY_BAN_REASON_MAX,\n COMMUNITY_DECLINE_REASON_MAX,\n COMMUNITY_DECLINE_REASON_MIN,\n COMMUNITY_DESCRIPTION_MAX,\n COMMUNITY_NAME_MAX,\n COMMUNITY_NAME_MIN,\n COMMUNITY_RULE_MAX,\n COMMUNITY_RULES_MAX,\n COMMUNITY_SUGGESTION_WHY_MAX,\n DAY_MS,\n DISCOVER_FILTER_VALUES_MAX,\n DISCOVER_TEXT_MAX,\n} from '../../core/limits.js';\nimport { paginatedSchema } from '../../core/responses.js';\nimport { VALIDATION_MESSAGE } from '../../core/validation.js';\nimport { mediaImageSchema } from '../media/media.js';\nimport { topicSchema } from '../onboarding/onboarding.js';\nimport { memberBylineSchema } from '../profile/founder-profile.js';\n\n/** Topics a community carries: what Discover filters by. */\nexport const COMMUNITY_TOPICS_MAX = 3;\n/** Announcements pinned to the top of one community at once. */\nexport const COMMUNITY_PINS_MAX = 3;\n/** Suggestions one member may have waiting for review at once. */\nexport const COMMUNITY_SUGGESTIONS_OPEN_MAX = 3;\n/**\n * The shortest time between two notify-everyone announcements in one\n * community, so members are not spammed (`COMMUNITY_ANNOUNCE_TOO_SOON`).\n */\nexport const COMMUNITY_ANNOUNCE_INTERVAL_MS = DAY_MS;\n\n// ─── Vocabulary ──────────────────────────────────────────────────────────────\n// ⚠ Every list below is STORED. Append only; removing a value orphans rows.\n\n/** See the module note's table. */\nexport const COMMUNITY_VISIBILITY_VALUES = ['public', 'private', 'hidden'] as const;\nexport const communityVisibilitySchema = z.enum(COMMUNITY_VISIBILITY_VALUES);\nexport type CommunityVisibility = z.infer<typeof communityVisibilitySchema>;\n\n/**\n * How private each type is, least first. A change to a LOWER rank exposes what\n * was already posted, so it needs `confirmExposure` (and is audited).\n */\nexport const COMMUNITY_VISIBILITY_RANK = {\n public: 0,\n private: 1,\n hidden: 2,\n} as const satisfies Record<CommunityVisibility, number>;\n\n/** Whether moving from one type to another exposes what was already there. */\nexport function communityChangeExposes(\n from: CommunityVisibility,\n to: CommunityVisibility,\n): boolean {\n return COMMUNITY_VISIBILITY_RANK[to] < COMMUNITY_VISIBILITY_RANK[from];\n}\n\n/** A member's role inside one community. */\nexport const COMMUNITY_ROLE_VALUES = ['admin', 'moderator', 'member'] as const;\nexport const communityRoleSchema = z.enum(COMMUNITY_ROLE_VALUES);\nexport type CommunityRole = z.infer<typeof communityRoleSchema>;\n\n/**\n * Where someone stands with one community. `requested` (private: waiting for\n * approval), `invited` (waiting for their answer), `banned` (the community is\n * hidden from them). Leaving or being removed deletes the row.\n */\nexport const COMMUNITY_MEMBER_STATUS_VALUES = ['active', 'requested', 'invited', 'banned'] as const;\nexport const communityMemberStatusSchema = z.enum(COMMUNITY_MEMBER_STATUS_VALUES);\nexport type CommunityMemberStatus = z.infer<typeof communityMemberStatusSchema>;\n\n/** `archived`: read-only and out of Discover; members still read it. Staff only. */\nexport const COMMUNITY_STATUS_VALUES = ['active', 'archived'] as const;\nexport const communityStatusSchema = z.enum(COMMUNITY_STATUS_VALUES);\nexport type CommunityStatus = z.infer<typeof communityStatusSchema>;\n\n/**\n * Whether a community may take type `to` now (0.18.0): ONE rule for the\n * server's refusal (`COMMUNITY_ARCHIVED`) and the screen's choice. An\n * archived community lets nobody new in, so it may be narrowed (private,\n * hidden) but never opened to public, which would let its waiting requests in.\n */\nexport function communityTypeChangeAllowed(\n status: CommunityStatus,\n to: CommunityVisibility,\n): boolean {\n return !(status === 'archived' && to === 'public');\n}\n\n/** How staff decided a suggestion (0.18.0: named, for the bell and the backend's model). */\nexport const COMMUNITY_SUGGESTION_DECISION_VALUES = ['approved', 'declined'] as const;\nexport const communitySuggestionDecisionSchema = z.enum(COMMUNITY_SUGGESTION_DECISION_VALUES);\nexport type CommunitySuggestionDecision = z.infer<typeof communitySuggestionDecisionSchema>;\nexport const COMMUNITY_SUGGESTION_STATUS_VALUES = [\n 'open',\n ...COMMUNITY_SUGGESTION_DECISION_VALUES,\n] as const;\nexport const communitySuggestionStatusSchema = z.enum(COMMUNITY_SUGGESTION_STATUS_VALUES);\nexport type CommunitySuggestionStatus = z.infer<typeof communitySuggestionStatusSchema>;\n\n// ─── Read shapes ─────────────────────────────────────────────────────────────\n\n/**\n * A community named on something else: \"in AI Builders\" on a post or poll, a\n * notification. `iconUrl` is the icon's smallest size.\n */\nexport const communityChipSchema = z.object({\n id: objectIdSchema,\n /** For a readable URL, `/communities/<id>/<slug>`. The id resolves; a renamed community keeps its links. */\n slug: z.string(),\n name: z.string(),\n iconUrl: z.url().optional(),\n visibility: communityVisibilitySchema,\n /** Present (true) once it is archived: read only, nobody takes part. */\n archived: z.boolean().optional(),\n});\nexport type CommunityChip = z.infer<typeof communityChipSchema>;\n\n/** Where THIS viewer stands with a community, on a card. Banned viewers never see it. */\nexport const communityCardViewerSchema = z.object({\n /** Null: not a member and nothing pending. Never `banned` (they get 404). */\n status: communityMemberStatusSchema.exclude(['banned']).nullable(),\n /** Their role while active, else null. */\n role: communityRoleSchema.nullable(),\n});\nexport type CommunityCardViewer = z.infer<typeof communityCardViewerSchema>;\n\n/** A community on Discover and in \"your communities\". */\nexport const communityCardSchema = z.object({\n id: objectIdSchema,\n slug: z.string(),\n name: z.string(),\n description: z.string(),\n icon: mediaImageSchema.optional(),\n visibility: communityVisibilitySchema,\n status: communityStatusSchema,\n topics: z.array(topicSchema).max(COMMUNITY_TOPICS_MAX),\n /** Active members. */\n memberCount: z.number().int().nonnegative(),\n /** Visible posts and polls in it. */\n postCount: z.number().int().nonnegative(),\n viewer: communityCardViewerSchema.optional(),\n});\nexport type CommunityCard = z.infer<typeof communityCardSchema>;\n\n/**\n * What THIS viewer may do on the community page, decided by the server and\n * sent as plain answers (the rule of `viewerStateSchema` on a post): a client\n * never derives a power from `role`.\n */\nexport const communityViewerSchema = communityCardViewerSchema.extend({\n /** Read its posts, polls and comments now. False on a private one before joining. */\n canRead: z.boolean(),\n /** Read its member list. */\n canSeeMembers: z.boolean(),\n /** Public, active, and the viewer has no row (nothing pending): offer Join. */\n canJoin: z.boolean(),\n /** Private, active, and the viewer has no row: offer Request to join. */\n canRequest: z.boolean(),\n /** Active member, community not archived: the composer. */\n canPost: z.boolean(),\n /**\n * Active member who is not its last admin, or the last admin of a community\n * nobody else is in (0.18.0): their leaving ARCHIVES it, nothing deleted,\n * since there is no one to hand it to. A last admin with members hands it\n * over first (`COMMUNITY_LAST_ADMIN`).\n */\n canLeave: z.boolean(),\n /**\n * Leaving ARCHIVES it (0.18.0): the viewer is its last admin and nobody else\n * is in it, counted as leaving counts. The server's answer, so the dialog\n * never guesses from a stored count.\n */\n leaveArchives: z.boolean(),\n /**\n * Moderators and admins (and managers, super admins): requests, invites,\n * pins, hiding, removing members. On an ARCHIVED community nobody new comes\n * in: approving, inviting, accepting, pinning AND opening it to public\n * (which would let waiting requests in, `communityTypeChangeAllowed`,\n * 0.18.0) answer `COMMUNITY_ARCHIVED`; narrowing its type, declining,\n * cancelling, removing, banning, roles and hiding still work.\n */\n canModerate: z.boolean(),\n /** Admins (and managers, super admins): details, icon, type, roles, bans. */\n canManage: z.boolean(),\n /**\n * Change members' roles (hand it over) and lift bans (0.13.0): every admin,\n * INCLUDING one whose membership ended and so cannot manage or moderate any\n * more. They keep this so a sole admin is never trapped: Manage shows them\n * Members (roles only) and Bans (unban only).\n */\n canAssign: z.boolean(),\n /** May notify every member with an announcement now (admins, at most once per `COMMUNITY_ANNOUNCE_INTERVAL_MS`). */\n canAnnounce: z.boolean(),\n /** Managers and super admins: archive, restore, delete. */\n canArchive: z.boolean(),\n});\nexport type CommunityViewer = z.infer<typeof communityViewerSchema>;\n\n/**\n * One person in a community, live-joined like every byline. In the member\n * list, admins first, then moderators, then members, each by when they joined.\n * `viewer` (0.9.0, on the member list only) is what THIS viewer may do to\n * them, the server's own rules (who outranks whom, never oneself, never the\n * last admin).\n */\nexport const communityMemberSchema = memberBylineSchema.extend({\n role: communityRoleSchema,\n joinedAt: z.iso.datetime(),\n viewer: z\n .object({\n canSetRole: z.boolean(),\n canRemove: z.boolean(),\n canBan: z.boolean(),\n })\n .optional(),\n});\nexport type CommunityMember = z.infer<typeof communityMemberSchema>;\n\n/** The community page. The header is what a non-member of a private one may see too. */\nexport const communitySchema = communityCardSchema.extend({\n rules: z.array(z.string()).max(COMMUNITY_RULES_MAX),\n /**\n * Its admins and moderators, admins first, by when they joined: who to ask.\n * EMPTY for a viewer who may not read it (a private community before\n * joining, a hidden one's invitee): who is in it is its members' to see.\n */\n team: z.array(communityMemberSchema),\n createdAt: z.iso.datetime(),\n updatedAt: z.iso.datetime(),\n archivedAt: z.iso.datetime().nullable(),\n /**\n * Only for managers and super admins: it has no admin left (its last one's\n * account was deleted where that cannot be refused), so staff run it until\n * they make a member admin, which clears it.\n */\n orphaned: z.boolean().optional(),\n viewer: communityViewerSchema.optional(),\n});\nexport type Community = z.infer<typeof communitySchema>;\n\n/** A request to join a private community, as its moderators see it. */\nexport const communityRequestSchema = z.object({\n member: memberBylineSchema,\n requestedAt: z.iso.datetime(),\n});\nexport type CommunityRequest = z.infer<typeof communityRequestSchema>;\n\n/** An invitation nobody has answered yet, as its moderators see it. */\nexport const communityPendingInviteSchema = z.object({\n member: memberBylineSchema,\n /** Null when whoever invited has since deleted their account. */\n invitedBy: memberBylineSchema.nullable(),\n invitedAt: z.iso.datetime(),\n});\nexport type CommunityPendingInvite = z.infer<typeof communityPendingInviteSchema>;\n\n/** An invitation waiting for the viewer's answer. */\nexport const communityInviteSchema = z.object({\n community: communityChipSchema.extend({ description: z.string() }),\n invitedBy: memberBylineSchema.nullable(),\n invitedAt: z.iso.datetime(),\n});\nexport type CommunityInvite = z.infer<typeof communityInviteSchema>;\n\n/** `GET /communities/invites`. Never paged: invitations are few, and each needs an answer. */\nexport const communityInvitesSchema = z.object({ items: z.array(communityInviteSchema) });\nexport type CommunityInvites = z.infer<typeof communityInvitesSchema>;\n\n/** Someone banned from a community, as its admins see it. */\nexport const communityBanSchema = z.object({\n member: memberBylineSchema,\n bannedBy: memberBylineSchema.nullable(),\n bannedAt: z.iso.datetime(),\n /** For the admins' own record; never shown to the banned member. */\n reason: z.string().max(COMMUNITY_BAN_REASON_MAX).optional(),\n});\nexport type CommunityBan = z.infer<typeof communityBanSchema>;\n\n/** A suggestion, as its author and the reviewers see it. */\nexport const communitySuggestionSchema = z.object({\n id: objectIdSchema,\n /** Null when its author has since deleted their account. */\n suggestedBy: memberBylineSchema.nullable(),\n name: z.string(),\n description: z.string(),\n why: z.string().optional(),\n visibility: communityVisibilitySchema,\n topics: z.array(topicSchema).max(COMMUNITY_TOPICS_MAX),\n status: communitySuggestionStatusSchema,\n decidedBy: memberBylineSchema.nullable(),\n decidedAt: z.iso.datetime().nullable(),\n /** Why it was declined, shown to its author. */\n declineReason: z.string().optional(),\n /**\n * The community it became, once approved. Absent if that community is since\n * deleted, or the viewer may no longer see it (banned from a hidden one).\n */\n community: communityChipSchema.optional(),\n createdAt: z.iso.datetime(),\n});\nexport type CommunitySuggestion = z.infer<typeof communitySuggestionSchema>;\n\nexport const communityCardPageSchema = paginatedSchema(communityCardSchema);\nexport type CommunityCardPage = z.infer<typeof communityCardPageSchema>;\nexport const communityMemberPageSchema = paginatedSchema(communityMemberSchema);\nexport type CommunityMemberPage = z.infer<typeof communityMemberPageSchema>;\nexport const communityRequestPageSchema = paginatedSchema(communityRequestSchema);\nexport type CommunityRequestPage = z.infer<typeof communityRequestPageSchema>;\nexport const communityPendingInvitePageSchema = paginatedSchema(communityPendingInviteSchema);\nexport type CommunityPendingInvitePage = z.infer<typeof communityPendingInvitePageSchema>;\nexport const communityBanPageSchema = paginatedSchema(communityBanSchema);\nexport type CommunityBanPage = z.infer<typeof communityBanPageSchema>;\nexport const communitySuggestionPageSchema = paginatedSchema(communitySuggestionSchema);\nexport type CommunitySuggestionPage = z.infer<typeof communitySuggestionPageSchema>;\n\n// ─── Queries and params ──────────────────────────────────────────────────────\n\n/**\n * `GET /communities`: public and private communities that are not archived\n * (hidden ones never), most members first. `q` matches the start of the\n * name; an emptied box (`?q=`) is no search, never a 400. `topic` means \"any of\".\n */\nexport const communityDiscoverQuerySchema = paginationQuerySchema.extend({\n q: optionalTrimmedString(DISCOVER_TEXT_MAX),\n topic: multiValueQuery(topicSchema, DISCOVER_FILTER_VALUES_MAX),\n});\nexport type CommunityDiscoverQuery = z.infer<typeof communityDiscoverQuerySchema>;\nexport type CommunityDiscoverQueryInput = z.input<typeof communityDiscoverQuerySchema>;\n\n/** `GET /communities/:id/members`: everyone, or one role (`?role=admin`). */\nexport const communityMembersQuerySchema = paginationQuerySchema.extend({\n role: z.preprocess(emptyStringToUndefined, communityRoleSchema.optional()),\n});\nexport type CommunityMembersQuery = z.infer<typeof communityMembersQuerySchema>;\nexport type CommunityMembersQueryInput = z.input<typeof communityMembersQuerySchema>;\n\n/** `GET /community-suggestions` (staff): waiting ones by default, oldest first. */\nexport const communitySuggestionsQuerySchema = paginationQuerySchema.extend({\n status: z.preprocess(emptyStringToUndefined, communitySuggestionStatusSchema.default('open')),\n});\nexport type CommunitySuggestionsQuery = z.infer<typeof communitySuggestionsQuerySchema>;\nexport type CommunitySuggestionsQueryInput = z.input<typeof communitySuggestionsQuerySchema>;\n\nexport const communityParamsSchema = z.object({ communityId: objectIdSchema });\nexport type CommunityParams = z.infer<typeof communityParamsSchema>;\n/** `/communities/:communityId/{members,requests,invites,bans}/:userId`. */\nexport const communityMemberParamsSchema = z.object({\n communityId: objectIdSchema,\n userId: objectIdSchema,\n});\nexport type CommunityMemberParams = z.infer<typeof communityMemberParamsSchema>;\n/** `/communities/:communityId/{pins,content}/:contentId`. */\nexport const communityContentParamsSchema = z.object({\n communityId: objectIdSchema,\n contentId: objectIdSchema,\n});\nexport type CommunityContentParams = z.infer<typeof communityContentParamsSchema>;\n/** `/communities/:communityId/comments/:commentId/hidden` (0.9.0). */\nexport const communityCommentParamsSchema = z.object({\n communityId: objectIdSchema,\n commentId: objectIdSchema,\n});\nexport type CommunityCommentParams = z.infer<typeof communityCommentParamsSchema>;\nexport const communitySuggestionParamsSchema = z.object({ suggestionId: objectIdSchema });\nexport type CommunitySuggestionParams = z.infer<typeof communitySuggestionParamsSchema>;\n\n// ─── Write bodies ────────────────────────────────────────────────────────────\n// Each its own object with NO defaults (see `updateFounderProfileBodySchema`).\n\nconst nameSchema = z.string().trim().min(COMMUNITY_NAME_MIN).max(COMMUNITY_NAME_MAX);\nconst descriptionSchema = z.string().trim().min(1).max(COMMUNITY_DESCRIPTION_MAX);\nconst rulesSchema = z\n .array(z.string().trim().min(1).max(COMMUNITY_RULE_MAX))\n .max(COMMUNITY_RULES_MAX);\nconst topicsSchema = z.array(topicSchema).max(COMMUNITY_TOPICS_MAX).refine(eachOnce, {\n error: VALIDATION_MESSAGE.topicsDuplicate,\n});\n\n/**\n * `POST /communities` (managers, super admins and capability holders), and\n * the reviewer's edited version when approving a suggestion. The creator\n * becomes its first admin. A name a live PUBLIC or PRIVATE community has is\n * `COMMUNITY_NAME_TAKEN` (letter case ignored, runs of spaces read as one);\n * hidden communities' names are never compared, so no name probes for one.\n * Approving a private or hidden one invites its suggester. The icon is a\n * processed `community_icon` upload.\n */\nexport const createCommunityBodySchema = z.object({\n name: nameSchema,\n description: descriptionSchema,\n visibility: communityVisibilitySchema,\n rules: rulesSchema.optional(),\n topics: topicsSchema.optional(),\n iconMediaId: objectIdSchema.optional(),\n});\nexport type CreateCommunityBody = z.infer<typeof createCommunityBodySchema>;\n\n/** `PATCH /communities/:id` (admins): only the keys that changed. Type and icon have their own routes. */\nexport const updateCommunityBodySchema = z.object({\n name: nameSchema.optional(),\n description: descriptionSchema.optional(),\n /** Sent whole; empty clears them. */\n rules: rulesSchema.optional(),\n topics: topicsSchema.optional(),\n});\nexport type UpdateCommunityBody = z.infer<typeof updateCommunityBodySchema>;\n\n/** `PUT /communities/:id/icon`: a processed `community_icon` upload. The old icon's files are deleted. */\nexport const setCommunityIconBodySchema = z.object({ mediaId: objectIdSchema });\nexport type SetCommunityIconBody = z.infer<typeof setCommunityIconBodySchema>;\n\n/**\n * `PUT /communities/:id/visibility` (admins). A change that exposes what was\n * already posted (`communityChangeExposes`: toward public, or hidden to\n * private) needs `confirmExposure: true`, else `COMMUNITY_EXPOSURE_UNCONFIRMED`:\n * the web asks first, and a client cannot skip the question. Audited.\n */\nexport const setCommunityVisibilityBodySchema = z.object({\n visibility: communityVisibilitySchema,\n confirmExposure: z.boolean().optional(),\n});\nexport type SetCommunityVisibilityBody = z.infer<typeof setCommunityVisibilityBodySchema>;\n\n/** `PUT /communities/:id/status` (staff). Audited. */\nexport const setCommunityStatusBodySchema = z.object({ status: communityStatusSchema });\nexport type SetCommunityStatusBody = z.infer<typeof setCommunityStatusBodySchema>;\n\n/**\n * `POST /communities/:id/invites` (moderators, private and hidden only;\n * a public community needs none: `COMMUNITY_INVITE_NOT_NEEDED`). Someone who\n * cannot join (not onboarded, paused, suspended, deleted) is\n * `COMMUNITY_MEMBER_NOT_INVITABLE`; banned, `COMMUNITY_MEMBER_BANNED`; already\n * a member, requested or invited, `COMMUNITY_ALREADY_MEMBER`.\n */\nexport const inviteCommunityMemberBodySchema = z.object({ userId: objectIdSchema });\nexport type InviteCommunityMemberBody = z.infer<typeof inviteCommunityMemberBodySchema>;\n\n/** `PUT /communities/:id/members/:userId/role` (admins). Never the last admin's own step down. */\nexport const setCommunityMemberRoleBodySchema = z.object({ role: communityRoleSchema });\nexport type SetCommunityMemberRoleBody = z.infer<typeof setCommunityMemberRoleBodySchema>;\n\n/** `POST /communities/:id/bans` (admins): removes them if active, and keeps them out. */\nexport const banCommunityMemberBodySchema = z.object({\n userId: objectIdSchema,\n /** Why, for the record. Blank means no reason (0.18.0: a blank box was refused). */\n reason: optionalTrimmedString(COMMUNITY_BAN_REASON_MAX),\n});\nexport type BanCommunityMemberBody = z.infer<typeof banCommunityMemberBodySchema>;\n\n/**\n * `POST /communities/:id/pins` (moderators): pin one of the community's posts\n * or polls as an announcement (`COMMUNITY_PINS_FULL` past `COMMUNITY_PINS_MAX`).\n * `notifyMembers` (admins only) rings every active member's bell, at most once\n * per `COMMUNITY_ANNOUNCE_INTERVAL_MS` (`COMMUNITY_ANNOUNCE_TOO_SOON`).\n */\nexport const pinCommunityContentBodySchema = z.object({\n contentId: objectIdSchema,\n notifyMembers: z.boolean(),\n});\nexport type PinCommunityContentBody = z.infer<typeof pinCommunityContentBodySchema>;\n\n/**\n * `POST /community-suggestions`: any onboarded member, at most\n * `COMMUNITY_SUGGESTIONS_OPEN_MAX` waiting at once (`COMMUNITY_SUGGESTIONS_FULL`).\n */\nexport const createCommunitySuggestionBodySchema = z.object({\n name: nameSchema,\n description: descriptionSchema,\n why: z.string().trim().min(1).max(COMMUNITY_SUGGESTION_WHY_MAX).optional(),\n visibility: communityVisibilitySchema,\n topics: topicsSchema.optional(),\n});\nexport type CreateCommunitySuggestionBody = z.infer<typeof createCommunitySuggestionBodySchema>;\n\n/**\n * `POST /community-suggestions/:id/decline` (staff): the reason is shown to the\n * suggester. A decided suggestion is `COMMUNITY_SUGGESTION_DECIDED`.\n */\nexport const declineCommunitySuggestionBodySchema = z.object({\n reason: z.string().trim().min(COMMUNITY_DECLINE_REASON_MIN).max(COMMUNITY_DECLINE_REASON_MAX),\n});\nexport type DeclineCommunitySuggestionBody = z.infer<typeof declineCommunitySuggestionBodySchema>;\n"]}
@@ -16,7 +16,7 @@
16
16
  * product receives, so the score cannot be bought with a popular product.
17
17
  *
18
18
  * Against farming: one member can earn at most `CONTRIBUTION_PAIR_POINTS_MAX`
19
- * points from any ONE other member over 30 days, so two founders cannot trade
19
+ * points from any ONE other member over `CONTRIBUTION_PAIR_WINDOW_DAYS`, so two founders cannot trade
20
20
  * Helpful marks into a high score.
21
21
  *
22
22
  * EVERY POINT IS A ROW (the ledger), so a score can be explained ("how did I
@@ -16,7 +16,7 @@
16
16
  * product receives, so the score cannot be bought with a popular product.
17
17
  *
18
18
  * Against farming: one member can earn at most `CONTRIBUTION_PAIR_POINTS_MAX`
19
- * points from any ONE other member over 30 days, so two founders cannot trade
19
+ * points from any ONE other member over `CONTRIBUTION_PAIR_WINDOW_DAYS`, so two founders cannot trade
20
20
  * Helpful marks into a high score.
21
21
  *
22
22
  * EVERY POINT IS A ROW (the ledger), so a score can be explained ("how did I
@@ -1 +1 @@
1
- {"version":3,"file":"contributions.js","sourceRoot":"","sources":["../../../src/domains/contributions/contributions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AAEnE,4CAA4C;AAC5C,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,kBAAkB;IAClB,kBAAkB;IAClB,gBAAgB;IAChB,gBAAgB;CACR,CAAC;AACX,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;AACvE;;;GAGG;AACH,MAAM,CAAC,MAAM,gCAAgC,GAAG,wBAAwB,CAAC,MAAM,CAC7E,CAAC,CAAC,EAA6E,EAAE,CAC/E,CAAC,KAAK,gBAAgB,CACzB,CAAC;AAGF;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,gBAAgB,EAAE,EAAE;IACpB,gBAAgB,EAAE,EAAE;IACpB,cAAc,EAAE,CAAC;IACjB,cAAc,EAAE,CAAC;CACkC,CAAC;AAEtD,4CAA4C;AAC5C,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,EAAE,EAAE,cAAc;IAClB,IAAI,EAAE,sBAAsB;IAC5B,gFAAgF;IAChF,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACnC;;;OAGG;IACH,KAAK,EAAE,kBAAkB,CAAC,QAAQ,EAAE;IACpC,iDAAiD;IACjD,OAAO,EAAE,iBAAiB,CAAC,QAAQ,EAAE;IACrC;;;OAGG;IACH,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,EAAE,EAAE,cAAc,EAAE,CAAC,CAAC,QAAQ,EAAE;IAC7E,SAAS,EAAE,cAAc,CAAC,QAAQ,EAAE;IACpC,QAAQ,EAAE,cAAc,CAAC,QAAQ,EAAE;IACnC,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE;CAC5B,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,sBAAsB,GAAG,eAAe,CAAC,uBAAuB,CAAC,CAAC;AAG/E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAU,CAAC;AACrE,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;AAG3E,gHAAgH;AAChH,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAC,CAAC,MAAM,CAAC;IACzD,0EAA0E;IAC1E,MAAM,EAAE,CAAC,CAAC,UAAU,CAAC,sBAAsB,EAAE,wBAAwB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;CACzF,CAAC,CAAC;AAGH,yEAAyE;AACzE,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC,MAAM,CAAC;IACpD,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACjC,MAAM,EAAE,kBAAkB;IAC1B,mCAAmC;IACnC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;CACpC,CAAC,CAAC;AAGH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5C,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAC5C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE;CACvC,CAAC,CAAC;AAGH;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC,MAAM,CAAC;IACpD,MAAM,EAAE,wBAAwB,CAAC,QAAQ,EAAE;IAC3C,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,6BAA6B,CAAC;IAC7C,GAAG,EAAE,qBAAqB,CAAC,QAAQ,EAAE;IACrC,UAAU,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;CACxC,CAAC,CAAC","sourcesContent":["/**\n * founder-schema — Contribution: the help a member gives, recognised\n *\n * The score counts HELP GIVEN, and only what OTHER members recognise:\n *\n * feedback_helpful a product's team marks your comment \"this helped\" +10\n * tester_confirmed a product's team confirms you tested their product +15\n * review_helpful another member finds your review helpful +2\n * (at most `REVIEW_HELPFUL_POINTS_MAX` per review)\n *\n * `review_written` is still listed so older rows and clients parse, but it is\n * NEVER awarded (0.7.0): writing a review is your own act, and the score\n * counts only what others recognise. A review earns through Helpful votes.\n *\n * Nothing a member does for their OWN product counts, and nothing their own\n * product receives, so the score cannot be bought with a popular product.\n *\n * Against farming: one member can earn at most `CONTRIBUTION_PAIR_POINTS_MAX`\n * points from any ONE other member over 30 days, so two founders cannot trade\n * Helpful marks into a high score.\n *\n * EVERY POINT IS A ROW (the ledger), so a score can be explained (\"how did I\n * earn this?\"), checked and re-tuned. A point stands while what earned it\n * stands: unmarking, withdrawing a vote, deleting the review or comment, or\n * staff removing it takes the point back. An hourly job recounts every score\n * from the ledger, so a total can never drift for long.\n *\n * Routes (all signed in):\n * GET /api/v1/contributions/me paginationQuerySchema -> contributionPageSchema\n * GET /api/v1/contributions/leaderboard contributionLeaderboardQuerySchema\n * -> contributionLeaderboardSchema\n *\n * The score itself is on the profile and the card (`contributionSummarySchema`).\n *\n * @module founder-schema/domains/contributions\n */\n\nimport { z } from 'zod';\nimport { emptyStringToUndefined, objectIdSchema } from '../../core/common.js';\nimport { paginatedSchema } from '../../core/responses.js';\nimport { contentKindSchema } from '../feed/feed.js';\nimport { productChipSchema } from '../products/products.js';\nimport { memberBylineSchema } from '../profile/founder-profile.js';\n\n/** ⚠ Stored per ledger row: append only. */\nexport const CONTRIBUTION_KIND_VALUES = [\n 'feedback_helpful',\n 'tester_confirmed',\n 'review_helpful',\n 'review_written',\n] as const;\nexport const contributionKindSchema = z.enum(CONTRIBUTION_KIND_VALUES);\n/**\n * The kinds that are actually awarded (0.7.0): every kind but `review_written`,\n * which is never awarded any more. \"How points are earned\" lists these.\n */\nexport const CONTRIBUTION_AWARDED_KIND_VALUES = CONTRIBUTION_KIND_VALUES.filter(\n (k): k is Exclude<(typeof CONTRIBUTION_KIND_VALUES)[number], 'review_written'> =>\n k !== 'review_written',\n);\nexport type ContributionKind = z.infer<typeof contributionKindSchema>;\n\n/**\n * Points per kind. Exhaustive by type. Changing a number changes FUTURE rows;\n * the hourly recount sums what each row was actually awarded.\n */\nexport const CONTRIBUTION_POINTS = {\n feedback_helpful: 10,\n tester_confirmed: 15,\n review_helpful: 2,\n review_written: 3,\n} as const satisfies Record<ContributionKind, number>;\n\n/** One line of \"how I earned my points\". */\nexport const contributionEntrySchema = z.object({\n id: objectIdSchema,\n kind: contributionKindSchema,\n /** What it was actually awarded: below the kind's points when a cap applied. */\n points: z.number().int().positive(),\n /**\n * Who recognised it; null for a deleted account, and for `review_helpful`\n * (a Helpful vote is anonymous: the review shows only a count).\n */\n actor: memberBylineSchema.nullable(),\n /** The product it was about, while it exists. */\n product: productChipSchema.optional(),\n /**\n * What earned it, so the row opens it: the post or poll and the comment for\n * `feedback_helpful`, the review for `review_helpful`.\n */\n content: z.object({ kind: contentKindSchema, id: objectIdSchema }).optional(),\n commentId: objectIdSchema.optional(),\n reviewId: objectIdSchema.optional(),\n createdAt: z.iso.datetime(),\n});\nexport type ContributionEntry = z.infer<typeof contributionEntrySchema>;\n\nexport const contributionPageSchema = paginatedSchema(contributionEntrySchema);\nexport type ContributionPage = z.infer<typeof contributionPageSchema>;\n\n/**\n * Which points a board ranks by (0.10.0): `recent`, the last\n * `CONTRIBUTION_RECENT_DAYS` days (the default, so a newer member can still\n * climb), or `all`, every point ever earned. Every board is GLOBAL: one list\n * for the whole circle (the user's ruling, 2026-10-11).\n */\nexport const CONTRIBUTION_PERIOD_VALUES = ['recent', 'all'] as const;\nexport const contributionPeriodSchema = z.enum(CONTRIBUTION_PERIOD_VALUES);\nexport type ContributionPeriod = z.infer<typeof contributionPeriodSchema>;\n\n/** `GET /api/v1/contributions/leaderboard?period=` (0.10.0). A query string, so the default is the server's. */\nexport const contributionLeaderboardQuerySchema = z.object({\n // `?period=` with nothing after it is no period, as on every other query.\n period: z.preprocess(emptyStringToUndefined, contributionPeriodSchema.default('recent')),\n});\nexport type ContributionLeaderboardQuery = z.infer<typeof contributionLeaderboardQuerySchema>;\n\n/** One row of a board: its rank, who, and their points in the period. */\nexport const contributionLeaderEntrySchema = z.object({\n rank: z.number().int().positive(),\n member: memberBylineSchema,\n /** Points earned in the period. */\n points: z.number().int().positive(),\n});\nexport type ContributionLeaderEntry = z.infer<typeof contributionLeaderEntrySchema>;\n\n/**\n * The signed-in member's own place on the board (0.10.0), on its first page or\n * not. Ranked in the SAME order, among the SAME members, as the list, so their\n * rank is always their position. `rank` is null while they are not on the\n * board: no points in the period (a board ranks help given, and nobody is\n * 40th for nothing), or a profile no longer listed. `points` are theirs either\n * way.\n */\nexport const contributionYouSchema = z.object({\n rank: z.number().int().positive().nullable(),\n points: z.number().int().nonnegative(),\n});\nexport type ContributionYou = z.infer<typeof contributionYouSchema>;\n\n/**\n * Top helpers, best first, at most `CONTRIBUTION_LEADERBOARD_SIZE`. Read from\n * the live counters, which move the moment help is recognised; only points\n * leaving the `recent` window wait for the hourly recount. `computedAt` is the\n * latest recount among the rows shown (null before the first run, and for an\n * empty board).\n *\n * `period` and `you` (0.10.0) are OPTIONAL on read, so this client keeps\n * parsing a server from before them: without `you` the board simply shows no\n * row of the member's own.\n */\nexport const contributionLeaderboardSchema = z.object({\n period: contributionPeriodSchema.optional(),\n items: z.array(contributionLeaderEntrySchema),\n you: contributionYouSchema.optional(),\n computedAt: z.iso.datetime().nullable(),\n});\nexport type ContributionLeaderboard = z.infer<typeof contributionLeaderboardSchema>;\n"]}
1
+ {"version":3,"file":"contributions.js","sourceRoot":"","sources":["../../../src/domains/contributions/contributions.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * founder-schema — Contribution: the help a member gives, recognised\n *\n * The score counts HELP GIVEN, and only what OTHER members recognise:\n *\n * feedback_helpful a product's team marks your comment \"this helped\" +10\n * tester_confirmed a product's team confirms you tested their product +15\n * review_helpful another member finds your review helpful +2\n * (at most `REVIEW_HELPFUL_POINTS_MAX` per review)\n *\n * `review_written` is still listed so older rows and clients parse, but it is\n * NEVER awarded (0.7.0): writing a review is your own act, and the score\n * counts only what others recognise. A review earns through Helpful votes.\n *\n * Nothing a member does for their OWN product counts, and nothing their own\n * product receives, so the score cannot be bought with a popular product.\n *\n * Against farming: one member can earn at most `CONTRIBUTION_PAIR_POINTS_MAX`\n * points from any ONE other member over `CONTRIBUTION_PAIR_WINDOW_DAYS`, so two founders cannot trade\n * Helpful marks into a high score.\n *\n * EVERY POINT IS A ROW (the ledger), so a score can be explained (\"how did I\n * earn this?\"), checked and re-tuned. A point stands while what earned it\n * stands: unmarking, withdrawing a vote, deleting the review or comment, or\n * staff removing it takes the point back. An hourly job recounts every score\n * from the ledger, so a total can never drift for long.\n *\n * Routes (all signed in):\n * GET /api/v1/contributions/me paginationQuerySchema -> contributionPageSchema\n * GET /api/v1/contributions/leaderboard contributionLeaderboardQuerySchema\n * -> contributionLeaderboardSchema\n *\n * The score itself is on the profile and the card (`contributionSummarySchema`).\n *\n * @module founder-schema/domains/contributions\n */\n\nimport { z } from 'zod';\nimport { emptyStringToUndefined, objectIdSchema } from '../../core/common.js';\nimport { paginatedSchema } from '../../core/responses.js';\nimport { contentKindSchema } from '../feed/feed.js';\nimport { productChipSchema } from '../products/products.js';\nimport { memberBylineSchema } from '../profile/founder-profile.js';\n\n/** ⚠ Stored per ledger row: append only. */\nexport const CONTRIBUTION_KIND_VALUES = [\n 'feedback_helpful',\n 'tester_confirmed',\n 'review_helpful',\n 'review_written',\n] as const;\nexport const contributionKindSchema = z.enum(CONTRIBUTION_KIND_VALUES);\n/**\n * The kinds that are actually awarded (0.7.0): every kind but `review_written`,\n * which is never awarded any more. \"How points are earned\" lists these.\n */\nexport const CONTRIBUTION_AWARDED_KIND_VALUES = CONTRIBUTION_KIND_VALUES.filter(\n (k): k is Exclude<(typeof CONTRIBUTION_KIND_VALUES)[number], 'review_written'> =>\n k !== 'review_written',\n);\nexport type ContributionKind = z.infer<typeof contributionKindSchema>;\n\n/**\n * Points per kind. Exhaustive by type. Changing a number changes FUTURE rows;\n * the hourly recount sums what each row was actually awarded.\n */\nexport const CONTRIBUTION_POINTS = {\n feedback_helpful: 10,\n tester_confirmed: 15,\n review_helpful: 2,\n review_written: 3,\n} as const satisfies Record<ContributionKind, number>;\n\n/** One line of \"how I earned my points\". */\nexport const contributionEntrySchema = z.object({\n id: objectIdSchema,\n kind: contributionKindSchema,\n /** What it was actually awarded: below the kind's points when a cap applied. */\n points: z.number().int().positive(),\n /**\n * Who recognised it; null for a deleted account, and for `review_helpful`\n * (a Helpful vote is anonymous: the review shows only a count).\n */\n actor: memberBylineSchema.nullable(),\n /** The product it was about, while it exists. */\n product: productChipSchema.optional(),\n /**\n * What earned it, so the row opens it: the post or poll and the comment for\n * `feedback_helpful`, the review for `review_helpful`.\n */\n content: z.object({ kind: contentKindSchema, id: objectIdSchema }).optional(),\n commentId: objectIdSchema.optional(),\n reviewId: objectIdSchema.optional(),\n createdAt: z.iso.datetime(),\n});\nexport type ContributionEntry = z.infer<typeof contributionEntrySchema>;\n\nexport const contributionPageSchema = paginatedSchema(contributionEntrySchema);\nexport type ContributionPage = z.infer<typeof contributionPageSchema>;\n\n/**\n * Which points a board ranks by (0.10.0): `recent`, the last\n * `CONTRIBUTION_RECENT_DAYS` days (the default, so a newer member can still\n * climb), or `all`, every point ever earned. Every board is GLOBAL: one list\n * for the whole circle (the user's ruling, 2026-10-11).\n */\nexport const CONTRIBUTION_PERIOD_VALUES = ['recent', 'all'] as const;\nexport const contributionPeriodSchema = z.enum(CONTRIBUTION_PERIOD_VALUES);\nexport type ContributionPeriod = z.infer<typeof contributionPeriodSchema>;\n\n/** `GET /api/v1/contributions/leaderboard?period=` (0.10.0). A query string, so the default is the server's. */\nexport const contributionLeaderboardQuerySchema = z.object({\n // `?period=` with nothing after it is no period, as on every other query.\n period: z.preprocess(emptyStringToUndefined, contributionPeriodSchema.default('recent')),\n});\nexport type ContributionLeaderboardQuery = z.infer<typeof contributionLeaderboardQuerySchema>;\n\n/** One row of a board: its rank, who, and their points in the period. */\nexport const contributionLeaderEntrySchema = z.object({\n rank: z.number().int().positive(),\n member: memberBylineSchema,\n /** Points earned in the period. */\n points: z.number().int().positive(),\n});\nexport type ContributionLeaderEntry = z.infer<typeof contributionLeaderEntrySchema>;\n\n/**\n * The signed-in member's own place on the board (0.10.0), on its first page or\n * not. Ranked in the SAME order, among the SAME members, as the list, so their\n * rank is always their position. `rank` is null while they are not on the\n * board: no points in the period (a board ranks help given, and nobody is\n * 40th for nothing), or a profile no longer listed. `points` are theirs either\n * way.\n */\nexport const contributionYouSchema = z.object({\n rank: z.number().int().positive().nullable(),\n points: z.number().int().nonnegative(),\n});\nexport type ContributionYou = z.infer<typeof contributionYouSchema>;\n\n/**\n * Top helpers, best first, at most `CONTRIBUTION_LEADERBOARD_SIZE`. Read from\n * the live counters, which move the moment help is recognised; only points\n * leaving the `recent` window wait for the hourly recount. `computedAt` is the\n * latest recount among the rows shown (null before the first run, and for an\n * empty board).\n *\n * `period` and `you` (0.10.0) are OPTIONAL on read, so this client keeps\n * parsing a server from before them: without `you` the board simply shows no\n * row of the member's own.\n */\nexport const contributionLeaderboardSchema = z.object({\n period: contributionPeriodSchema.optional(),\n items: z.array(contributionLeaderEntrySchema),\n you: contributionYouSchema.optional(),\n computedAt: z.iso.datetime().nullable(),\n});\nexport type ContributionLeaderboard = z.infer<typeof contributionLeaderboardSchema>;\n"]}
@@ -7,7 +7,8 @@
7
7
  * screen can be glanced at over a shoulder. Each block answers one question:
8
8
  * is the community growing, is it talking, is anything waiting on staff.
9
9
  *
10
- * "Last 7 days" is the seven days up to `generatedAt`, by the server's clock.
10
+ * "Last 7 days" is the `DASHBOARD_RECENT_DAYS` days up to `generatedAt`, by the
11
+ * server's clock (the field names say 7: changing the constant renames them).
11
12
  *
12
13
  * @module founder-schema/domains/dashboard
13
14
  */
@@ -31,6 +32,7 @@ export declare const dashboardSchema: z.ZodObject<{
31
32
  }, z.core.$strip>;
32
33
  support: z.ZodObject<{
33
34
  openTickets: z.ZodNumber;
35
+ waitingTickets: z.ZodNumber;
34
36
  unassignedTickets: z.ZodNumber;
35
37
  }, z.core.$strip>;
36
38
  billing: z.ZodObject<{
@@ -1 +1 @@
1
- {"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../../src/domains/dashboard/dashboard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAuD1B,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC"}
1
+ {"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../../../src/domains/dashboard/dashboard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAsE1B,CAAC;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC"}