Coverage for app/backend/src/couchers/constants.py: 100%

53 statements  

« prev     ^ index     » next       coverage.py v7.15.3, created at 2026-08-04 22:32 +0000

1from datetime import UTC, datetime, timedelta 

2 

3# terms of service version 

4TOS_VERSION = 2 

5 

6# community guidelines version 

7GUIDELINES_VERSION = 1 

8 

9# When updating this, also update the "activeness_probe" notification strings in 

10# src/couchers/email/locales/en.json 

11LATEST_RELEASE_BLOG_URL = "https://couchers.org/blog/2026/05/25/couchers-spring-release" 

12 

13EMAIL_REGEX = r"^[0-9a-z]([0-9a-z\-\_\+]|(\.[0-9a-z\-\_\+]))*@([0-9a-z\-]+\.)*[0-9a-z\-]+\.[a-z]{2,}$" 

14 

15# Must match the frontend values in app/web/utils/validation.ts 

16VALID_NAME_MIN_LENGTH = 2 

17VALID_NAME_MAX_LENGTH = 100 

18 

19# Letters, diacritics, internal spaces, quotes, dashes, commas, dots, and's for two names. See tests! 

20VALID_NAME_REGEX = r"""^(?!\p{Zs})[\p{L}\p{M}\p{Zs}\p{Pi}\p{Pf}\p{Pd},.'"·・&/|]+(?<!\p{Zs})$""" 

21 

22BANNED_USERNAME_PHRASES = [ 

23 "admin", 

24 "bot", 

25 "safety", 

26 "security", 

27 "secure", 

28 "trust", 

29 "couchers", 

30 "help", 

31 "moderation", 

32 "moderator", 

33 "noreply", 

34 "official", 

35 "security", 

36 "staff", 

37 "support", 

38 "system", 

39 "team", 

40 "verify", 

41] 

42 

43# expiry time for a verified phone number 

44PHONE_VERIFICATION_LIFETIME = timedelta(days=2 * 365) 

45 

46# shortest period between phone verification code requests 

47PHONE_REVERIFICATION_INTERVAL = timedelta(days=2) 

48 

49# expiry time for an sms code 

50SMS_CODE_LIFETIME = timedelta(hours=24) 

51 

52# max attempts to enter the sms code 

53SMS_CODE_ATTEMPTS = 3 

54 

55# Postal verification constants 

56POSTAL_VERIFICATION_CODE_LENGTH = 6 

57# Reduced alphabet to avoid confusion (no I, O, 0, 1) 

58POSTAL_VERIFICATION_CODE_ALPHABET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789" 

59# Code valid for 90 days after postcard sent 

60POSTAL_VERIFICATION_CODE_LIFETIME = timedelta(days=90) 

61# Max wrong code attempts before lockout 

62POSTAL_VERIFICATION_MAX_ATTEMPTS = 5 

63# Can only initiate once per 30 days 

64POSTAL_VERIFICATION_RATE_LIMIT = timedelta(days=30) 

65 

66SIGNUP_EMAIL_TOKEN_VALIDITY = timedelta(hours=48) 

67 

68DATETIME_MINUS_INFINITY = datetime(1, 1, 1, tzinfo=UTC) 

69DATETIME_INFINITY = datetime(9876, 12, 31, hour=23, minute=59, second=59, tzinfo=UTC) 

70 

71# the api workers listen on API_BASE_PORT .. API_BASE_PORT + API_WORKER_COUNT - 1; must stay in sync with 

72# proxy/envoy.yaml and docker-compose.prod.yml 

73API_WORKER_COUNT = 4 

74API_BASE_PORT = 1761 

75MEDIA_PORT = 1753 

76 

77# per API worker process; kept small since we parallelize across processes (API_WORKER_COUNT), not threads 

78SERVER_THREADS = 8 

79 

80# SQLAlchemy pool size, per process; sized for the API workers as the larger consumer, see db.py 

81DB_POOL_SIZE = 2 * SERVER_THREADS + 4 

82 

83# on SIGTERM, how long to let in-flight RPCs drain before the server is forced down; kept under the 

84# container's stop_grace_period (docker-compose stop_grace_period: 30s) so workers drain, not SIGKILLed 

85GRACEFUL_SHUTDOWN_TIMEOUT = 5 

86 

87# how long the user has to undelete their account 

88UNDELETE_DAYS = 7 

89 

90# expiry time for preferred language cookie 

91PREFERRED_LANGUAGE_COOKIE_EXPIRY = timedelta(days=3650) 

92 

93 

94# activeness probe settings 

95# wait about 11 months before sending one out 

96ACTIVENESS_PROBE_INACTIVITY_PERIOD = timedelta(days=333) 

97# times at which to send notifications after inactivity (cumulative since start of probe) 

98ACTIVENESS_PROBE_TIME_REMINDERS = [timedelta(days=0), timedelta(days=2, hours=8)] 

99# total time from initiation after which to expire the probe 

100ACTIVENESS_PROBE_EXPIRY_TIME = timedelta(days=4) 

101 

102HOST_REQUEST_MAX_REMINDERS = 1 

103HOST_REQUEST_REMINDER_INTERVAL = timedelta(days=2) 

104 

105HOST_REQUEST_DUPLICATE_WINDOW_HOURS = 3 

106 

107# Note: Javascript's string.length is in utf16 code units, Python's len(str) is in utf8 code units. 

108HOST_REQUEST_MIN_LENGTH_UTF16 = 250 # Must match frontend 

109PUBLIC_TRIP_DESCRIPTION_MIN_LENGTH_UTF16 = 150 # Must match frontend 

110 

111ANTIBOT_FREQ = timedelta(hours=48) 

112 

113EVENT_REMINDER_TIMEDELTA = timedelta(hours=24) 

114 

115COMMUNITIES_SEARCH_FUZZY_SIMILARITY_THRESHOLD = 0.35 

116 

117UNKNOWN_ERROR_MESSAGE = "An unknown backend error occurred. Please consider filing a bug!" 

118 

119# NOTE: these codes are on purpose not translatable 

120NONEXISTENT_API_CALL_ERROR_MESSAGE = "API call does not exist. Please refresh and try again." 

121MISSING_AUTH_LEVEL_ERROR_MESSAGE = "Internal authentication error." 

122COOKIES_AND_AUTH_HEADER_ERROR_MESSAGE = 'Both "cookie" and "authorization" in request' 

123CALL_CANCELLED_ERROR_MESSAGE = "Call cancelled." 

124 

125# NOTE: the frontend uses these (and error codes) to distinguish between jailed and logged out 

126UNAUTHORIZED_ERROR_MESSAGE = "Unauthorized" 

127PERMISSION_DENIED_ERROR_MESSAGE = "Permission denied" 

128 

129GHOST_USERNAME = "ghost" 

130 

131# Photo gallery limits 

132GALLERY_MAX_PHOTOS_NOT_VERIFIED = 2 

133GALLERY_MAX_PHOTOS_VERIFIED = 5 

134 

135COMPLETED_PROFILE_MINIMUM_CHAR_LENGTH = 150 

136 

137# How long a container must run uninterrupted before /status reports stable=true 

138STABLE_THRESHOLD_SECONDS = 5 * 60 

139 

140MODERATION_AUTO_APPROVE_FLAG_PRIORITY = 1000