Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion scripts/check-access-clock.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { pathToFileURL } from "node:url";

const ROOT = path.resolve(import.meta.dirname, "..");

Expand All @@ -31,7 +32,7 @@ async function loadViewers() {
v = v.replace(/^import\s+\{[^}]*\}\s+from\s+["']\.\/types["'];?\s*$/m,
'import { TIER_RANK, normalizeTier } from "./types.ts";');
fs.writeFileSync(path.join(tmp, "viewers.ts"), v);
return import(path.join(tmp, "viewers.ts"));
return import(pathToFileURL(path.join(tmp, "viewers.ts")).href);
}

const { canRead, resolveTier, FIXED_NOW } = await loadViewers();
Expand Down
5 changes: 3 additions & 2 deletions scripts/check-mcp-keys.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { createHash, createHmac } from "node:crypto";
import { pathToFileURL } from "node:url";

const ROOT = path.resolve(import.meta.dirname, "..");
const sha256Hex = (s) => createHash("sha256").update(s).digest("hex");
Expand Down Expand Up @@ -67,7 +68,7 @@ async function loadResolver() {
'import { normalizeTier } from "./types.ts";');
fs.copyFileSync(path.join(ROOT, "lib/auth/mcp-pepper.mjs"), path.join(tmp, "mcp-pepper.mjs"));
fs.writeFileSync(path.join(tmp, "mcp-keys.ts"), m);
return import(path.join(tmp, "mcp-keys.ts"));
return import(pathToFileURL(path.join(tmp, "mcp-keys.ts")).href);
}
const { resolveMcpKeyCap } = await loadResolver();
const now = Date.now();
Expand All @@ -81,7 +82,7 @@ console.log('[check:mcp-keys] ✓ with no MCP_API_KEYS store, every key (incl. t

// ── Guard 2b: an HMAC-keyed store entry grants its tier; expiry is honoured; unknown tier never escalates;
// unminted formats, a missing pepper and a bare-SHA-256 (pre-R2) store never resolve. ──
const { mintMcpKey } = await import(path.join(ROOT, "scripts/mint-mcp-key.mjs"));
const { mintMcpKey } = await import(pathToFileURL(path.join(ROOT, "scripts/mint-mcp-key.mjs")).href);
const pepper = "test-only-pepper-0123456789-abcdefghij"; // test-only, >= 8 distinct chars
const good = mintMcpKey({ pepper, tier: "academic", sub: "org:academic_partner", expiresAt: now + 30 * 86_400_000 });
const expired = mintMcpKey({ pepper, tier: "academic", sub: "org:stale", expiresAt: now - 1 });
Expand Down
5 changes: 3 additions & 2 deletions scripts/gen-changelog.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@
// fail-soft: with no MEM_GATEWAY_URL / MEM_CONNECT_SECRET (e.g. a local build)
// or an unreachable gateway, it writes a graceful placeholder rather than
// failing the build. Protocol mirrors lib/ai/memory.ts.
import { createHmac } from "node:crypto";
import fs from "node:fs";
import path from "node:path";
import { createHmac } from "node:crypto";
import { fileURLToPath } from "node:url";
import { changelogRepos } from "./lib/changelog-repos.mjs";

const ROOT = path.resolve(path.dirname(new URL(import.meta.url).pathname), "..");
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
const OUT_DIR = path.join(ROOT, "content", "start", "_generated");
const OUT = path.join(OUT_DIR, "changelog.md");

Expand Down
18 changes: 18 additions & 0 deletions test/changelog-tiers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
* changelog now selects repos with the SAME policy: only repos that resolve to
* "public" for the chat are recalled onto the public page.
*/
import { readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
import { describe, it, expect } from "vitest";
import { resolveRepoTiers, repoTierFrom } from "@/lib/ai/memory";
// @ts-expect-error -- plain ESM helper shared with scripts/gen-changelog.mjs
Expand All @@ -13,6 +15,22 @@ import { changelogRepos } from "@/scripts/lib/changelog-repos.mjs";
const CANDIDATES = ["citrate-chain", "citrate-core", "citrate-inference-gateway", "citrate-identity", "citrate-docs", "citrate-sdk-js", "citrate-security"];

describe("changelog repo selection matches the chat tier policy", () => {
it("decodes file URLs without losing Windows drive paths", () => {
const fileUrl = new URL("file:///C:/repo/Github%20Federated/citrate-docs/scripts/gen-changelog.mjs");
const filePath = fileURLToPath(fileUrl);

expect(filePath).not.toContain("%20");
if (process.platform === "win32") {
expect(filePath).toBe("C:\\repo\\Github Federated\\citrate-docs\\scripts\\gen-changelog.mjs");
} else {
expect(filePath).toBe("/C:/repo/Github Federated/citrate-docs/scripts/gen-changelog.mjs");
}

const generator = readFileSync(fileURLToPath(new URL("../scripts/gen-changelog.mjs", import.meta.url)), "utf8");
expect(generator).toContain("fileURLToPath(import.meta.url)");
expect(generator).not.toContain("new URL(import.meta.url).pathname");
});

it("with default config no federation repo is public, so none is recalled", () => {
expect(changelogRepos({})).toEqual([]);
});
Expand Down
Loading