Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
8c5467a
feat(cli): add encrypted token store to integration templates
kojiwakayama Aug 3, 2026
bbdba82
chore: drop unused stringifyJsonValue imports to unblock pre-push lint
kojiwakayama Aug 3, 2026
5bd3b15
Harden generated token row normalization
kojiwakayama Aug 3, 2026
211d76d
Keep generated integration manifest current
kojiwakayama Aug 3, 2026
a58a573
Keep generated OAuth storage fail closed under bad state
kojiwakayama Aug 3, 2026
621d660
Reconcile encrypted storage with the current release baseline
kojiwakayama Aug 3, 2026
c0e3ad0
Harden generated OAuth token metadata validation
kojiwakayama Aug 3, 2026
4e81376
Constrain OAuth state skew to future timestamps
kojiwakayama Aug 3, 2026
b3c9fbf
fix(cli): harden generated OAuth token storage
kojiwakayama Aug 3, 2026
6e69f20
Prevent inherited serializers from shaping encrypted rows
kojiwakayama Aug 3, 2026
55292cf
feat(cli): support key rotation and degraded reads in encrypted token…
kwakayama Aug 3, 2026
19aef36
fix(cli): redact encrypted token row failures
kojiwakayama Aug 3, 2026
88f9bf1
fix(cli): bound encrypted token JSON snapshots
kojiwakayama Aug 3, 2026
fcaefb0
test(cli): use valid null prototype sentinel
kojiwakayama Aug 3, 2026
aa4dea7
Make encrypted OAuth rotation and state failures observable
kojiwakayama Aug 3, 2026
3c848a8
feat(cli): re-seal rotated encrypted token rows on read
kwakayama Aug 3, 2026
cec8713
Keep rotation reports from trusting malformed encrypted rows
kojiwakayama Aug 3, 2026
c3a3ba6
fix(cli): keep encrypted token storage keys distinct
kojiwakayama Aug 3, 2026
dabe464
fix(cli): preserve OAuth refresh capabilities
kojiwakayama Aug 3, 2026
f968a1e
test(cli): tighten encryption rotation checks
kojiwakayama Aug 3, 2026
8fa1d4f
test(cli): assert exact sanitized token-store warnings
kojiwakayama Aug 3, 2026
5a0c750
Keep generated token stores fail-closed without env access
kojiwakayama Aug 3, 2026
d6f9b5e
Keep stale OAuth state out of rotation gates
kojiwakayama Aug 3, 2026
24ade64
Align token-store template guidance with test mode
kojiwakayama Aug 3, 2026
6c974b2
Preserve refresh tokens omitted by OAuth providers
kojiwakayama Aug 3, 2026
67dc85d
Keep generated token stores fail-closed under process env denial
kojiwakayama Aug 3, 2026
aeafe66
Align generated memory-backend guidance with test mode
kojiwakayama Aug 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,369 changes: 1,369 additions & 0 deletions cli/encrypted-token-store-template.test.ts

Large diffs are not rendered by default.

65 changes: 63 additions & 2 deletions cli/templates/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -412,17 +412,32 @@ describe("cli/templates", () => {
"./integrations/_base/files/lib/token-store.ts",
import.meta.url,
);
const tokenStoreExamplesPath = new URL(
"./integrations/_base/files/lib/token-store-examples.ts",
import.meta.url,
);
const tokenStore = await Deno.readTextFile(tokenStorePath);
const tokenStoreExamples = await Deno.readTextFile(tokenStoreExamplesPath);

assertEquals(
tokenStore.includes("createDefaultTokenStore"),
true,
"token-store.ts should centralize default store selection",
);
assertEquals(
tokenStore.includes("OAuth token storage is not configured for production"),
tokenStore.includes("only when NODE_ENV is explicitly development or test"),
true,
"token-store.ts should fail closed outside explicit development and test modes",
);
assertEquals(
tokenStore.includes("The built-in memory store is for development and test."),
true,
"token-store.ts should fail closed for production memory storage",
"token-store.ts header should match the development/test memory-store guard",
);
assertEquals(
tokenStoreExamples.includes("Development/test in-memory backend."),
true,
"token-store-examples.ts should match the development/test memory-store guard",
);
assertEquals(
tokenStore.includes("getDefaultTokenStore"),
Expand Down Expand Up @@ -456,6 +471,52 @@ describe("cli/templates", () => {
);
});

it("generated OAuth refresh helpers use the shared lock and CAS protocol", async () => {
const integrationTemplates = new URL("./integrations/", import.meta.url);
const offenders: string[] = [];
let helperCount = 0;

for (const file of await collectTemplateTsFiles(integrationTemplates)) {
const source = await Deno.readTextFile(file);
if (!source.includes("export async function getValidToken(")) continue;

helperCount++;
if (
!source.includes("getRefreshableAccessToken(") ||
source.includes("tokenStore.setToken(") ||
source.includes("tokenStore.revokeToken(")
) {
offenders.push(file.pathname.replace(integrationTemplates.pathname, ""));
}
}

assertEquals(helperCount, 3, "Expected every generated getValidToken implementation");
assertEquals(
offenders,
[],
`OAuth refresh helpers must use the shared lock/CAS protocol. Offenders: ${
offenders.join(", ")
}`,
);
});

Comment thread
coderabbitai[bot] marked this conversation as resolved.
it("keeps Gmail on the shared refresh-capable token store", async () => {
const gmailClient = await Deno.readTextFile(
new URL("./integrations/gmail/files/lib/gmail-client.ts", import.meta.url),
);

assertEquals(
gmailClient.includes("new OAuthService(gmailConfig, tokenStore)"),
true,
"Gmail must preserve the shared store's refresh lock and revisioned CAS methods",
);
assertEquals(
gmailClient.includes("tokenStoreAdapter"),
false,
"Gmail must not narrow the refresh-capable token store contract",
);
});

it("OAuth route templates use the central shared token store", async () => {
const integrationTemplates = new URL("./integrations/", import.meta.url);
const offenders: string[] = [];
Expand Down
Loading