mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-27 21:01:03 +08:00
fix(tests): stub canonical HEXCLAVE_* env names so dual-read doesn't shadow/conflict
The env-var rename added conflict-detecting dual-read (HEXCLAVE_* wins over STACK_*, throws when both differ) and set HEXCLAVE_* to non-empty values in the checked-in .env.development files. Tests that stubbed the legacy STACK_* twin either triggered the conflict throw or were silently shadowed by the canonical HEXCLAVE_* value loaded from .env. Point the test env stubs at the canonical HEXCLAVE_* names (production reads keep the legacy STACK_* argument and rely on dual-read): - plan-entitlements.test.ts: HEXCLAVE_DISABLE_PLAN_LIMITS - turnstile.tsx / users.tsx: HEXCLAVE_DISABLE_BOT_CHALLENGE, HEXCLAVE_ALLOW_SIGN_UP_ON_VISIBLE_BOT_CHALLENGE_FAILURE - access-token-helpers.tsx: HEXCLAVE_ALLOW_SHARED_OAUTH_ACCESS_TOKENS - url-targets.test.ts: NEXT_PUBLIC_HEXCLAVE_HOSTED_HANDLER_* Also fix the turnstile dev-secret-key test to clear both twins so it actually exercises the dev-key fallback instead of passing on a string coincidence.
This commit is contained in:
parent
261d3c6e64
commit
7539fb9fbf
@ -45,7 +45,7 @@ export function isSharedAccessTokenBlocked(providerIsShared: boolean): boolean {
|
||||
import.meta.vitest?.describe("isSharedAccessTokenBlocked", () => {
|
||||
const { test, expect, beforeEach, afterEach, vi } = import.meta.vitest!;
|
||||
beforeEach(() => {
|
||||
vi.stubEnv("STACK_ALLOW_SHARED_OAUTH_ACCESS_TOKENS", "");
|
||||
vi.stubEnv("HEXCLAVE_ALLOW_SHARED_OAUTH_ACCESS_TOKENS", "");
|
||||
});
|
||||
afterEach(() => {
|
||||
vi.unstubAllEnvs();
|
||||
@ -53,7 +53,7 @@ import.meta.vitest?.describe("isSharedAccessTokenBlocked", () => {
|
||||
|
||||
test("non-shared provider is never blocked, regardless of env var", () => {
|
||||
expect(isSharedAccessTokenBlocked(false)).toBe(false);
|
||||
vi.stubEnv("STACK_ALLOW_SHARED_OAUTH_ACCESS_TOKENS", "true");
|
||||
vi.stubEnv("HEXCLAVE_ALLOW_SHARED_OAUTH_ACCESS_TOKENS", "true");
|
||||
expect(isSharedAccessTokenBlocked(false)).toBe(false);
|
||||
});
|
||||
|
||||
@ -63,22 +63,22 @@ import.meta.vitest?.describe("isSharedAccessTokenBlocked", () => {
|
||||
|
||||
test("shared provider is blocked for any value other than the literal 'true'", () => {
|
||||
for (const v of ["false", "1", "TRUE", "yes", " true "]) {
|
||||
vi.stubEnv("STACK_ALLOW_SHARED_OAUTH_ACCESS_TOKENS", v);
|
||||
vi.stubEnv("HEXCLAVE_ALLOW_SHARED_OAUTH_ACCESS_TOKENS", v);
|
||||
expect(isSharedAccessTokenBlocked(true)).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
test("shared provider is allowed only when env var === 'true'", () => {
|
||||
vi.stubEnv("STACK_ALLOW_SHARED_OAUTH_ACCESS_TOKENS", "true");
|
||||
vi.stubEnv("HEXCLAVE_ALLOW_SHARED_OAUTH_ACCESS_TOKENS", "true");
|
||||
expect(isSharedAccessTokenBlocked(true)).toBe(false);
|
||||
});
|
||||
|
||||
test("result does not depend on NODE_ENV", () => {
|
||||
for (const nodeEnv of ["production", "development", "test", "preview", ""]) {
|
||||
vi.stubEnv("NODE_ENV", nodeEnv);
|
||||
vi.stubEnv("STACK_ALLOW_SHARED_OAUTH_ACCESS_TOKENS", "");
|
||||
vi.stubEnv("HEXCLAVE_ALLOW_SHARED_OAUTH_ACCESS_TOKENS", "");
|
||||
expect(isSharedAccessTokenBlocked(true)).toBe(true);
|
||||
vi.stubEnv("STACK_ALLOW_SHARED_OAUTH_ACCESS_TOKENS", "true");
|
||||
vi.stubEnv("HEXCLAVE_ALLOW_SHARED_OAUTH_ACCESS_TOKENS", "true");
|
||||
expect(isSharedAccessTokenBlocked(true)).toBe(false);
|
||||
}
|
||||
});
|
||||
|
||||
@ -194,25 +194,25 @@ describe("arePlanLimitsEnforced", () => {
|
||||
});
|
||||
|
||||
it("returns true when env var is unset (default-on enforcement)", () => {
|
||||
vi.stubEnv("STACK_DISABLE_PLAN_LIMITS", "");
|
||||
vi.stubEnv("HEXCLAVE_DISABLE_PLAN_LIMITS", "");
|
||||
expect(arePlanLimitsEnforced()).toBe(true);
|
||||
});
|
||||
|
||||
it("returns false when env var is exactly 'true'", () => {
|
||||
vi.stubEnv("STACK_DISABLE_PLAN_LIMITS", "true");
|
||||
vi.stubEnv("HEXCLAVE_DISABLE_PLAN_LIMITS", "true");
|
||||
expect(arePlanLimitsEnforced()).toBe(false);
|
||||
});
|
||||
|
||||
it("returns true when env var is 'false'", () => {
|
||||
vi.stubEnv("STACK_DISABLE_PLAN_LIMITS", "false");
|
||||
vi.stubEnv("HEXCLAVE_DISABLE_PLAN_LIMITS", "false");
|
||||
expect(arePlanLimitsEnforced()).toBe(true);
|
||||
});
|
||||
|
||||
it("returns true for any non-'true' value (e.g. '1', 'yes', 'TRUE')", () => {
|
||||
// Explicit string match is intentional — we don't want to risk a typo
|
||||
// like STACK_DISABLE_PLAN_LIMITS=trueee silently disabling enforcement.
|
||||
// like HEXCLAVE_DISABLE_PLAN_LIMITS=trueee silently disabling enforcement.
|
||||
for (const value of ["1", "yes", "TRUE", "True", " true", "true ", "trueee"]) {
|
||||
vi.stubEnv("STACK_DISABLE_PLAN_LIMITS", value);
|
||||
vi.stubEnv("HEXCLAVE_DISABLE_PLAN_LIMITS", value);
|
||||
expect(arePlanLimitsEnforced()).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
@ -360,8 +360,12 @@ import.meta.vitest?.describe("verifyTurnstileToken(...)", () => {
|
||||
test("uses development secret key when none is configured", async ({ expect }) => {
|
||||
const processEnv = Reflect.get(process, "env");
|
||||
const originalNodeEnv = Reflect.get(processEnv, "NODE_ENV");
|
||||
const originalKey = Reflect.get(processEnv, "STACK_TURNSTILE_SECRET_KEY");
|
||||
const originalHexclaveKey = Reflect.get(processEnv, "HEXCLAVE_TURNSTILE_SECRET_KEY");
|
||||
const originalStackKey = Reflect.get(processEnv, "STACK_TURNSTILE_SECRET_KEY");
|
||||
Reflect.set(processEnv, "NODE_ENV", "development");
|
||||
// Clear both spellings so the value resolves to the dev-key default; the
|
||||
// canonical HEXCLAVE_ name is set in .env.development and otherwise wins.
|
||||
Reflect.set(processEnv, "HEXCLAVE_TURNSTILE_SECRET_KEY", "");
|
||||
Reflect.set(processEnv, "STACK_TURNSTILE_SECRET_KEY", "");
|
||||
|
||||
let postedSecret = "";
|
||||
@ -380,7 +384,16 @@ import.meta.vitest?.describe("verifyTurnstileToken(...)", () => {
|
||||
.resolves.toEqual({ status: "ok" });
|
||||
} finally {
|
||||
Reflect.set(processEnv, "NODE_ENV", originalNodeEnv);
|
||||
Reflect.set(processEnv, "STACK_TURNSTILE_SECRET_KEY", originalKey);
|
||||
for (const [key, original] of [
|
||||
["HEXCLAVE_TURNSTILE_SECRET_KEY", originalHexclaveKey],
|
||||
["STACK_TURNSTILE_SECRET_KEY", originalStackKey],
|
||||
] as const) {
|
||||
if (original === undefined) {
|
||||
Reflect.deleteProperty(processEnv, key);
|
||||
} else {
|
||||
Reflect.set(processEnv, key, original);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
expect(postedSecret).toBe(turnstileDevelopmentKeys.secretKey);
|
||||
@ -390,25 +403,25 @@ import.meta.vitest?.describe("verifyTurnstileToken(...)", () => {
|
||||
import.meta.vitest?.describe("verifyTurnstileTokenWithOptionalVisibleChallenge(...)", () => {
|
||||
const { vi, test, afterEach, beforeEach } = import.meta.vitest!;
|
||||
const processEnv = Reflect.get(process, "env");
|
||||
const originalFlag = Reflect.get(processEnv, "STACK_ALLOW_SIGN_UP_ON_VISIBLE_BOT_CHALLENGE_FAILURE");
|
||||
const originalDisableFlag = Reflect.get(processEnv, "STACK_DISABLE_BOT_CHALLENGE");
|
||||
const originalFlag = Reflect.get(processEnv, "HEXCLAVE_ALLOW_SIGN_UP_ON_VISIBLE_BOT_CHALLENGE_FAILURE");
|
||||
const originalDisableFlag = Reflect.get(processEnv, "HEXCLAVE_DISABLE_BOT_CHALLENGE");
|
||||
|
||||
beforeEach(() => {
|
||||
Reflect.deleteProperty(processEnv, "STACK_ALLOW_SIGN_UP_ON_VISIBLE_BOT_CHALLENGE_FAILURE");
|
||||
Reflect.deleteProperty(processEnv, "STACK_DISABLE_BOT_CHALLENGE");
|
||||
Reflect.deleteProperty(processEnv, "HEXCLAVE_ALLOW_SIGN_UP_ON_VISIBLE_BOT_CHALLENGE_FAILURE");
|
||||
Reflect.deleteProperty(processEnv, "HEXCLAVE_DISABLE_BOT_CHALLENGE");
|
||||
});
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
vi.unstubAllGlobals();
|
||||
if (originalFlag === undefined) {
|
||||
Reflect.deleteProperty(processEnv, "STACK_ALLOW_SIGN_UP_ON_VISIBLE_BOT_CHALLENGE_FAILURE");
|
||||
Reflect.deleteProperty(processEnv, "HEXCLAVE_ALLOW_SIGN_UP_ON_VISIBLE_BOT_CHALLENGE_FAILURE");
|
||||
} else {
|
||||
Reflect.set(processEnv, "STACK_ALLOW_SIGN_UP_ON_VISIBLE_BOT_CHALLENGE_FAILURE", originalFlag);
|
||||
Reflect.set(processEnv, "HEXCLAVE_ALLOW_SIGN_UP_ON_VISIBLE_BOT_CHALLENGE_FAILURE", originalFlag);
|
||||
}
|
||||
if (originalDisableFlag === undefined) {
|
||||
Reflect.deleteProperty(processEnv, "STACK_DISABLE_BOT_CHALLENGE");
|
||||
Reflect.deleteProperty(processEnv, "HEXCLAVE_DISABLE_BOT_CHALLENGE");
|
||||
} else {
|
||||
Reflect.set(processEnv, "STACK_DISABLE_BOT_CHALLENGE", originalDisableFlag);
|
||||
Reflect.set(processEnv, "HEXCLAVE_DISABLE_BOT_CHALLENGE", originalDisableFlag);
|
||||
}
|
||||
});
|
||||
|
||||
@ -448,7 +461,7 @@ import.meta.vitest?.describe("verifyTurnstileTokenWithOptionalVisibleChallenge(.
|
||||
});
|
||||
|
||||
test("skips all bot challenge verification when disabled", async ({ expect }) => {
|
||||
Reflect.set(processEnv, "STACK_DISABLE_BOT_CHALLENGE", "true");
|
||||
Reflect.set(processEnv, "HEXCLAVE_DISABLE_BOT_CHALLENGE", "true");
|
||||
const fetchSpy = vi.fn();
|
||||
vi.stubGlobal("fetch", fetchSpy);
|
||||
|
||||
@ -463,7 +476,7 @@ import.meta.vitest?.describe("verifyTurnstileTokenWithOptionalVisibleChallenge(.
|
||||
});
|
||||
|
||||
test("can downgrade visible invalid responses into a scored assessment when bypass is enabled", async ({ expect }) => {
|
||||
Reflect.set(processEnv, "STACK_ALLOW_SIGN_UP_ON_VISIBLE_BOT_CHALLENGE_FAILURE", "true");
|
||||
Reflect.set(processEnv, "HEXCLAVE_ALLOW_SIGN_UP_ON_VISIBLE_BOT_CHALLENGE_FAILURE", "true");
|
||||
vi.stubGlobal("fetch", async () => new Response(JSON.stringify({ success: false }), {
|
||||
status: 200, headers: { "Content-Type": "application/json" },
|
||||
}));
|
||||
|
||||
@ -115,17 +115,17 @@ import.meta.vitest?.test("getDerivedSignUpCountryCode", ({ expect }) => {
|
||||
import.meta.vitest?.describe("visible bot challenge sign-up policy", () => {
|
||||
const { expect, test, beforeEach, afterEach } = import.meta.vitest!;
|
||||
const processEnv = Reflect.get(process, "env");
|
||||
const originalFlag = Reflect.get(processEnv, "STACK_ALLOW_SIGN_UP_ON_VISIBLE_BOT_CHALLENGE_FAILURE");
|
||||
const originalFlag = Reflect.get(processEnv, "HEXCLAVE_ALLOW_SIGN_UP_ON_VISIBLE_BOT_CHALLENGE_FAILURE");
|
||||
|
||||
beforeEach(() => {
|
||||
Reflect.deleteProperty(processEnv, "STACK_ALLOW_SIGN_UP_ON_VISIBLE_BOT_CHALLENGE_FAILURE");
|
||||
Reflect.deleteProperty(processEnv, "HEXCLAVE_ALLOW_SIGN_UP_ON_VISIBLE_BOT_CHALLENGE_FAILURE");
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
if (originalFlag === undefined) {
|
||||
Reflect.deleteProperty(processEnv, "STACK_ALLOW_SIGN_UP_ON_VISIBLE_BOT_CHALLENGE_FAILURE");
|
||||
Reflect.deleteProperty(processEnv, "HEXCLAVE_ALLOW_SIGN_UP_ON_VISIBLE_BOT_CHALLENGE_FAILURE");
|
||||
} else {
|
||||
Reflect.set(processEnv, "STACK_ALLOW_SIGN_UP_ON_VISIBLE_BOT_CHALLENGE_FAILURE", originalFlag);
|
||||
Reflect.set(processEnv, "HEXCLAVE_ALLOW_SIGN_UP_ON_VISIBLE_BOT_CHALLENGE_FAILURE", originalFlag);
|
||||
}
|
||||
});
|
||||
|
||||
@ -137,7 +137,7 @@ import.meta.vitest?.describe("visible bot challenge sign-up policy", () => {
|
||||
});
|
||||
|
||||
test("allows sign-up when visible challenge failure override is enabled", () => {
|
||||
Reflect.set(processEnv, "STACK_ALLOW_SIGN_UP_ON_VISIBLE_BOT_CHALLENGE_FAILURE", "true");
|
||||
Reflect.set(processEnv, "HEXCLAVE_ALLOW_SIGN_UP_ON_VISIBLE_BOT_CHALLENGE_FAILURE", "true");
|
||||
|
||||
expect(() => assertVisibleBotChallengePassedForSignUp({
|
||||
status: "error",
|
||||
@ -146,7 +146,7 @@ import.meta.vitest?.describe("visible bot challenge sign-up policy", () => {
|
||||
});
|
||||
|
||||
test("treats invalid visible challenges as bypassable failures when the override is enabled", () => {
|
||||
Reflect.set(processEnv, "STACK_ALLOW_SIGN_UP_ON_VISIBLE_BOT_CHALLENGE_FAILURE", "true");
|
||||
Reflect.set(processEnv, "HEXCLAVE_ALLOW_SIGN_UP_ON_VISIBLE_BOT_CHALLENGE_FAILURE", "true");
|
||||
|
||||
expect(() => assertVisibleBotChallengePassedForSignUp({
|
||||
status: "invalid",
|
||||
|
||||
@ -81,7 +81,7 @@ describe("handler URL targets", () => {
|
||||
});
|
||||
|
||||
it("uses hosted defaults for unspecified URLs", () => {
|
||||
vi.stubEnv("NEXT_PUBLIC_STACK_HOSTED_HANDLER_DOMAIN_SUFFIX", ".example-stack-hosted.test");
|
||||
vi.stubEnv("NEXT_PUBLIC_HEXCLAVE_HOSTED_HANDLER_DOMAIN_SUFFIX", ".example-stack-hosted.test");
|
||||
|
||||
const urls = resolveHandlerUrls({
|
||||
projectId: "project-id",
|
||||
@ -97,7 +97,7 @@ describe("handler URL targets", () => {
|
||||
});
|
||||
|
||||
it("keeps redirect-only post-auth targets local even when the default target is hosted", () => {
|
||||
vi.stubEnv("NEXT_PUBLIC_STACK_HOSTED_HANDLER_DOMAIN_SUFFIX", ".example-stack-hosted.test");
|
||||
vi.stubEnv("NEXT_PUBLIC_HEXCLAVE_HOSTED_HANDLER_DOMAIN_SUFFIX", ".example-stack-hosted.test");
|
||||
|
||||
const urls = resolveHandlerUrls({
|
||||
projectId: "project-id",
|
||||
@ -141,7 +141,7 @@ describe("handler URL targets", () => {
|
||||
});
|
||||
|
||||
it("inherits a hosted default target for the OAuth callback", () => {
|
||||
vi.stubEnv("NEXT_PUBLIC_STACK_HOSTED_HANDLER_DOMAIN_SUFFIX", ".example-stack-hosted.test");
|
||||
vi.stubEnv("NEXT_PUBLIC_HEXCLAVE_HOSTED_HANDLER_DOMAIN_SUFFIX", ".example-stack-hosted.test");
|
||||
|
||||
const urls = resolveHandlerUrls({
|
||||
projectId: "project-id",
|
||||
@ -179,7 +179,7 @@ describe("handler URL targets", () => {
|
||||
});
|
||||
|
||||
it("uses default target for unknown /handler/* pages", () => {
|
||||
vi.stubEnv("NEXT_PUBLIC_STACK_HOSTED_HANDLER_DOMAIN_SUFFIX", ".example-stack-hosted.test");
|
||||
vi.stubEnv("NEXT_PUBLIC_HEXCLAVE_HOSTED_HANDLER_DOMAIN_SUFFIX", ".example-stack-hosted.test");
|
||||
|
||||
const url = resolveUnknownHandlerPathFallbackUrl({
|
||||
defaultTarget: { type: "hosted" },
|
||||
@ -191,7 +191,7 @@ describe("handler URL targets", () => {
|
||||
});
|
||||
|
||||
it("uses the full hosted handler URL template when configured", () => {
|
||||
vi.stubEnv("NEXT_PUBLIC_STACK_HOSTED_HANDLER_URL_TEMPLATE", "http://{projectId}.localhost:${NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX:-81}09/{hostedPath}");
|
||||
vi.stubEnv("NEXT_PUBLIC_HEXCLAVE_HOSTED_HANDLER_URL_TEMPLATE", "http://{projectId}.localhost:${NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX:-81}09/{hostedPath}");
|
||||
vi.stubEnv("NEXT_PUBLIC_HEXCLAVE_PORT_PREFIX", "93");
|
||||
|
||||
const urls = resolveHandlerUrls({
|
||||
@ -206,7 +206,7 @@ describe("handler URL targets", () => {
|
||||
});
|
||||
|
||||
it("validates the hosted handler URL template placeholders", () => {
|
||||
vi.stubEnv("NEXT_PUBLIC_STACK_HOSTED_HANDLER_URL_TEMPLATE", "http://localhost:9309/{projectId}/handler");
|
||||
vi.stubEnv("NEXT_PUBLIC_HEXCLAVE_HOSTED_HANDLER_URL_TEMPLATE", "http://localhost:9309/{projectId}/handler");
|
||||
|
||||
expect(() => resolveHandlerUrls({
|
||||
projectId: "project-id",
|
||||
@ -217,7 +217,7 @@ describe("handler URL targets", () => {
|
||||
});
|
||||
|
||||
it("rejects hosted handler URL templates that put the project ID in the path", () => {
|
||||
vi.stubEnv("NEXT_PUBLIC_STACK_HOSTED_HANDLER_URL_TEMPLATE", "http://localhost:9309/{projectId}/{hostedPath}");
|
||||
vi.stubEnv("NEXT_PUBLIC_HEXCLAVE_HOSTED_HANDLER_URL_TEMPLATE", "http://localhost:9309/{projectId}/{hostedPath}");
|
||||
|
||||
expect(() => resolveHandlerUrls({
|
||||
projectId: "project-id",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user