Drop GOOGLE_REFRESH_TOKEN env seeding; link Calendar only via /connect_calendar

This commit is contained in:
EugeneTes
2026-09-24 20:10:03 +00:00
parent 4a14148d05
commit a5e5796d18
6 changed files with 5 additions and 38 deletions

View File

@@ -21,9 +21,6 @@ LOG_LEVEL=info
# /connect_calendar and follow the two-step flow — no refresh token needed here.
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
# Deprecated. If set at startup, seeded once into workspace/.secretary/google-token.json
# and then ignored. Use /connect_calendar in the bot for new setups.
GOOGLE_REFRESH_TOKEN=
# Playwright browser tools (MCP bridge). When PLAYWRIGHT_ENABLED=true the agent
# gets ~60 browser_* tools (navigate, click, type, screenshot, run arbitrary

View File

@@ -98,7 +98,6 @@ The agent's edits to `MEMORY.md` are local runtime data. Leave them uncommitted,
| `CAPTCHA_API_KEY` | no | | Captcha solver key; enables `fortress_solve_captcha` and auto-solve during fetch |
| `GOOGLE_CLIENT_ID` | no | | OAuth client id (TVs and Limited Input devices) — enables the calendar tool |
| `GOOGLE_CLIENT_SECRET` | no | | OAuth client secret — required alongside `GOOGLE_CLIENT_ID` |
| `GOOGLE_REFRESH_TOKEN` | no | | Deprecated. If set, seeded once into `workspace/.secretary/google-token.json`, then ignored. |
## Keeping it running on Windows

View File

@@ -17,7 +17,6 @@ services:
- LOG_LEVEL=${LOG_LEVEL:-info}
- GOOGLE_CLIENT_ID=${GOOGLE_CLIENT_ID:-}
- GOOGLE_CLIENT_SECRET=${GOOGLE_CLIENT_SECRET:-}
- GOOGLE_REFRESH_TOKEN=${GOOGLE_REFRESH_TOKEN:-}
- FORTRESS_ENABLED=${FORTRESS_ENABLED:-false}
- FORTRESS_HEADLESS=${FORTRESS_HEADLESS:-true}
- FORTRESS_CHANNEL=${FORTRESS_CHANNEL:-}

View File

@@ -72,25 +72,12 @@ describe("loadConfig", () => {
});
});
it("accepts Google client_id + client_secret without a refresh token", () => {
it("accepts Google client_id + client_secret", () => {
const cfg = loadConfig(
{ ...base, GOOGLE_CLIENT_ID: "cid", GOOGLE_CLIENT_SECRET: "csecret" },
"/p",
);
expect(cfg.google).toEqual({ clientId: "cid", clientSecret: "csecret", refreshToken: undefined });
});
it("accepts Google client_id + client_secret + refresh_token together", () => {
const cfg = loadConfig(
{
...base,
GOOGLE_CLIENT_ID: "cid",
GOOGLE_CLIENT_SECRET: "csecret",
GOOGLE_REFRESH_TOKEN: "rt",
},
"/p",
);
expect(cfg.google).toEqual({ clientId: "cid", clientSecret: "csecret", refreshToken: "rt" });
expect(cfg.google).toEqual({ clientId: "cid", clientSecret: "csecret" });
});
it("rejects Google config that has client_id without client_secret", () => {
@@ -105,12 +92,6 @@ describe("loadConfig", () => {
).toThrow(/GOOGLE_CLIENT_ID.*GOOGLE_CLIENT_SECRET/);
});
it("rejects a lone GOOGLE_REFRESH_TOKEN without client_id/secret", () => {
expect(() =>
loadConfig({ ...base, GOOGLE_REFRESH_TOKEN: "rt" }, "/p"),
).toThrow(/GOOGLE_CLIENT_ID.*GOOGLE_CLIENT_SECRET/);
});
it("leaves google undefined when no GOOGLE_* vars are set", () => {
expect(loadConfig(base, "/p").google).toBeUndefined();
});

View File

@@ -19,7 +19,6 @@ export interface Config {
export interface GoogleConfig {
clientId: string;
clientSecret: string;
refreshToken?: string;
}
export interface PlaywrightConfig {
@@ -65,17 +64,16 @@ export function loadConfig(env: NodeJS.ProcessEnv = process.env, cwd: string = p
const googleClientId = blankToUndefined(env.GOOGLE_CLIENT_ID);
const googleClientSecret = blankToUndefined(env.GOOGLE_CLIENT_SECRET);
const googleRefreshToken = blankToUndefined(env.GOOGLE_REFRESH_TOKEN);
const hasClientId = Boolean(googleClientId);
const hasClientSecret = Boolean(googleClientSecret);
if (hasClientId !== hasClientSecret || (!hasClientId && googleRefreshToken)) {
if (hasClientId !== hasClientSecret) {
throw new ConfigError(
"Google Calendar needs both GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET (refresh token is optional; if set at startup it will be migrated into the workspace store).",
"Google Calendar needs both GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET.",
);
}
const google: GoogleConfig | undefined =
googleClientId && googleClientSecret
? { clientId: googleClientId, clientSecret: googleClientSecret, refreshToken: googleRefreshToken }
? { clientId: googleClientId, clientSecret: googleClientSecret }
: undefined;
const playwright: PlaywrightConfig | undefined = parseBool(env.PLAYWRIGHT_ENABLED)

View File

@@ -91,13 +91,6 @@ async function main(): Promise<void> {
let tokenStore: GoogleTokenStore | null = null;
if (config.google) {
tokenStore = createGoogleTokenStore(config.workspaceDir);
if (config.google.refreshToken && tokenStore.read() === null) {
tokenStore.write(config.google.refreshToken);
logger.warn(
"GOOGLE_REFRESH_TOKEN env var seeded into workspace/.secretary/google-token.json. " +
"You can remove GOOGLE_REFRESH_TOKEN from .env now — future updates come through /connect_calendar.",
);
}
customTools.push(createCalendarTool({
clientId: config.google.clientId,
clientSecret: config.google.clientSecret,