Skip to content

Commit 759405f

Browse files
tyler-daneclaude
andauthored
Remove in-app email opt-in; automate list sync outside the repo (#2759)
* Remove in-app email opt-in; automate list sync outside the repo The 45-second-delayed subscribe modal was hard to time well and added config surface (EMAILER_SECRET, email: in compass.yaml, a Kit service, two API routes) that no self-hoster ever needs. New signups are now added to Kit by a scheduled job in compass-calendar-infra instead, so the app itself no longer knows the list exists. A tolerant `email:` schema entry keeps existing self-hosted compass.yaml files valid on upgrade. A one-line consent notice replaces the modal on the signup form. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Remove genericError and SUBSCRIBE_TO_UPDATES_TOAST_ID left orphaned Both were only ever used by the Kit email code removed in the prior commit; knip caught them as dead exports. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
1 parent e738502 commit 759405f

37 files changed

Lines changed: 16 additions & 1220 deletions

.github/workflows/_deploy-environment.yml

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ jobs:
8585
COMPASS_SYNC_TOKEN: ${{ secrets.COMPASS_SYNC_TOKEN }}
8686
GCAL_NOTIFICATION_TOKEN: ${{ secrets.GCAL_NOTIFICATION_TOKEN }}
8787
GOOGLE_CLIENT_SECRET: ${{ secrets.GOOGLE_CLIENT_SECRET }}
88-
KIT_API_SECRET: ${{ secrets.KIT_API_SECRET }}
8988
MONGO_PASSWORD: ${{ secrets.MONGO_PASSWORD }}
9089
MONGO_REPLICA_SET_KEY: ${{ secrets.MONGO_REPLICA_SET_KEY }}
9190
MONGO_URI: ${{ secrets.MONGO_URI }}
@@ -105,10 +104,6 @@ jobs:
105104
# (2026-08-01).
106105
if [ "${{ inputs.environment }}" = "production" ]; then
107106
NODE_ENV="production"
108-
if [ -z "$KIT_API_SECRET" ]; then
109-
echo "Production deploy requires KIT_API_SECRET." >&2
110-
exit 1
111-
fi
112107
else
113108
NODE_ENV="staging"
114109
fi
@@ -186,11 +181,6 @@ jobs:
186181
" key: \"${POSTHOG_KEY}\"" \
187182
" host: \"${POSTHOG_HOST}\""
188183
fi
189-
if [ -n "$KIT_API_SECRET" ]; then
190-
printf '%s\n' \
191-
'email:' \
192-
" kitApiSecret: \"${KIT_API_SECRET}\""
193-
fi
194184
printf '%s\n' \
195185
'sync:' \
196186
" mongoUri: \"${SYNC_MONGO_URI}\"" \

compass.example.yaml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,6 @@ supertokens:
3737
# clientId: REPLACE_WITH_GOOGLE_CLIENT_ID # e.g. your-id.apps.googleusercontent.com
3838
# clientSecret: REPLACE_WITH_GOOGLE_CLIENT_SECRET
3939

40-
# email:
41-
# kitApiSecret: REPLACE_WITH_KIT_API_SECRET
42-
4340
# posthog:
4441
# key: REPLACE_WITH_POSTHOG_KEY
4542
# host: REPLACE_WITH_POSTHOG_HOST

docs/Config/README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,5 @@ database and must not share the backend's database user/data.
9696

9797
| key | Required | Description |
9898
|---|---|---|
99-
| `email.kitApiSecret` | No | Kit.com API secret key. |
10099
| `posthog.key` | No | PostHog project key injected into the web bundle. |
101100
| `posthog.host` | No | PostHog host injected into the web bundle. |
Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import type request from "supertest";
22
import { Status } from "@core/errors/status.codes";
3-
import { type EmailUpdatesResponse } from "@core/types/email/email.types";
43
import { type UserProfile } from "@core/types/user.types";
54
import { type BaseDriver } from "@backend/__tests__/drivers/base.driver";
65
import { type Summary_Delete } from "@backend/user/types/user.types";
@@ -29,26 +28,4 @@ export class UserControllerDriver {
2928
.use(this.baseDriver.setSessionPlugin(session))
3029
.expect(status);
3130
}
32-
33-
async getEmailUpdates(
34-
session?: { userId: string },
35-
status: Status = Status.OK,
36-
): Promise<Omit<request.Response, "body"> & { body: EmailUpdatesResponse }> {
37-
return this.baseDriver
38-
.getServer()
39-
.get("/api/user/email-updates")
40-
.use(this.baseDriver.setSessionPlugin(session))
41-
.expect(status);
42-
}
43-
44-
async subscribeToEmailUpdates(
45-
session?: { userId: string },
46-
status: Status = Status.OK,
47-
): Promise<Omit<request.Response, "body"> & { body: EmailUpdatesResponse }> {
48-
return this.baseDriver
49-
.getServer()
50-
.put("/api/user/email-updates")
51-
.use(this.baseDriver.setSessionPlugin(session))
52-
.expect(status);
53-
}
5431
}

packages/backend/src/common/constants/config.constants.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ const ConfigSchema = z
2121
GOOGLE_CLIENT_ID: z.string().nonempty().optional(),
2222
GOOGLE_CLIENT_SECRET: z.string().nonempty().optional(),
2323
DB: z.string().nonempty(),
24-
EMAILER_SECRET: z.string().nonempty().optional(),
2524
FRONTEND_URL: z.string().url(),
2625
MONGO_URI: z.string().nonempty(),
2726
NODE_ENV: z.nativeEnum(NodeEnv),
@@ -84,7 +83,6 @@ export function parseRawConfig(config: CompassConfig): Config {
8483
GOOGLE_CLIENT_ID: nonEmpty(config.google?.clientId),
8584
GOOGLE_CLIENT_SECRET: nonEmpty(config.google?.clientSecret),
8685
DB: isDev(nodeEnv) ? "dev_calendar" : "prod_calendar",
87-
EMAILER_SECRET: nonEmpty(config.email?.kitApiSecret),
8886
FRONTEND_URL: config.web.url,
8987
MONGO_URI: config.mongo.uri,
9088
NODE_ENV: nodeEnv,
@@ -113,7 +111,6 @@ export function parseConfigFromEnv(
113111
GOOGLE_CLIENT_ID: rawEnv["GOOGLE_CLIENT_ID"],
114112
GOOGLE_CLIENT_SECRET: rawEnv["GOOGLE_CLIENT_SECRET"],
115113
DB: isDev(nodeEnv) ? "dev_calendar" : "prod_calendar",
116-
EMAILER_SECRET: rawEnv["EMAILER_API_SECRET"],
117114
FRONTEND_URL: rawEnv["FRONTEND_URL"],
118115
MONGO_URI: rawEnv["MONGO_URI"],
119116
NODE_ENV: nodeEnv,

packages/backend/src/common/errors/emailer/emailer.errors.ts

Lines changed: 0 additions & 28 deletions
This file was deleted.

packages/backend/src/common/errors/handlers/error.handler.ts

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { BaseError } from "@core/errors/errors.base";
2-
import { Status } from "@core/errors/status.codes";
32
import { Logger } from "@core/logger/winston.logger";
43
import { type ErrorMetadata } from "@backend/common/types/error.types";
54

@@ -21,19 +20,6 @@ export const error = (cause: ErrorMetadata, result: string) => {
2120
);
2221
};
2322

24-
export const genericError = (
25-
e: unknown,
26-
result: string,
27-
status = Status.INTERNAL_SERVER,
28-
isOperational = true,
29-
) => {
30-
const _e = e as Error;
31-
const name = _e.name || "GenericName";
32-
const description = `${name}: ${_e.message || "GenericMsg"}`;
33-
const cause = { description, isOperational, status };
34-
return error(cause, result);
35-
};
36-
3723
/**
3824
* Returns a safe payload for BaseError to send to clients.
3925
* Avoids exposing stack, isOperational, or other internal details.

packages/backend/src/email/email.service.test.ts

Lines changed: 0 additions & 82 deletions
This file was deleted.

0 commit comments

Comments
 (0)