fix(grok): synchronize launcher admission and numeric expiry refresh

Handle supported numeric credential expiries and verify launcher digests across the TypeScript, Rust, server, and provider-pack boundaries.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-09-24 12:01:20 -07:00
1 parent d20e8a5c2e
commit bc6833f716
7 files changed
+41 -8

No files matched your search

+6 -1
View File
@@ -38,7 +38,12 @@ if (!environment.XAI_API_KEY && environment.GROK_HOME && isAbsolute(environment.
if (error.code !== "ENOENT") throw new Error("Grok subscription credential is invalid");
}
const entries = auth && typeof auth === "object" && !Array.isArray(auth) ? Object.values(auth) : [];
const expiry = entries.length === 1 ? Date.parse(entries[0]?.expires_at) : NaN;
const rawExpiry = entries.length === 1 ? entries[0]?.expires_at : undefined;
// Match the managed Grok auth contract: ISO-8601, epoch seconds, or milliseconds.
const isoExpiry = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/;
const expiry = typeof rawExpiry === "number" && Number.isFinite(rawExpiry)
? rawExpiry < 1e12 ? rawExpiry * 1000 : rawExpiry
: typeof rawExpiry === "string" && isoExpiry.test(rawExpiry) ? Date.parse(rawExpiry) : NaN;
if (Number.isFinite(expiry) && expiry <= Date.now() + 60_000) {
// Descriptor-backed executables must retain their exact descriptor in the
// child. Other descriptors, including ACP stdin/stdout, are not forwarded.
@@ -168,7 +168,7 @@ impl AcpxProviderDescriptor {
"1.0.13",
Some("@paperclipai/grok-acp"),
Some("1.0.13"),
"sha256:42fe296ec6fc0715c3509cec9671451bcd5bfdc7f185041101c8aac1e9ac8718",
"sha256:f0b698395a3704ed2ffaf84ea19bdb20c36c8a0a70b7c629c7b6ffe144e59e55",
),
"pi" => return Err(DurableRunnerError::invalid(
"ACPX agent pi is not executable through the verified runnerd provider boundary",
@@ -314,7 +314,7 @@ try {
.update(distDigest)
.digest("hex")}`,
acpxProfileDigests: {
grok: "sha256:42fe296ec6fc0715c3509cec9671451bcd5bfdc7f185041101c8aac1e9ac8718",
grok: "sha256:f0b698395a3704ed2ffaf84ea19bdb20c36c8a0a70b7c629c7b6ffe144e59e55",
claude:
"sha256:9d73d1f0f121fb96cc8badb28c22d5bff02d8582eb2e40360a81c189e1b9422a",
codex:
@@ -2118,15 +2118,29 @@ async function installationFixture() {
describe("Grok launcher subscription refresh", () => {
it("keeps the Grok launcher digest synchronized across TypeScript, Rust, server, and provider pack", async () => {
const launcher = await readFile(new URL("../../../../grok-acp/launcher.cjs", import.meta.url));
const digest = `sha256:${createHash("sha256").update(launcher).digest("hex")}`;
expect(resolveQualifiedAcpxProfile("grok", "grok-4.7").commandDigest).toBe(digest);
const [server, pack, rust] = await Promise.all([
readFile(new URL("../../../../../server/src/services/native-runtime/native-session-executor.ts", import.meta.url), "utf8"),
readFile(new URL("../../../scripts/build-provider-pack.mjs", import.meta.url), "utf8"),
readFile(new URL("../../../runner/crates/runner-core/src/acpx_provider_backend.rs", import.meta.url), "utf8"),
]);
expect(server).toContain(`grok: "${digest}"`);
expect(pack).toContain(`grok: "${digest}"`);
expect(rust.split('"grok" =>')[1]?.slice(0, 600)).toContain(`"${digest}"`);
});
async function fixture(input: {
expiry?: number; apiKey?: string; executable?: string;
expiry?: number; rawExpiry?: unknown; apiKey?: string; executable?: string;
refresh?: { status: number | null; signal?: string | null; error?: Error };
mode?: number; fileError?: string; growingFile?: boolean;
} = {}) {
const script = await readFile(new URL("../../../../grok-acp/launcher.cjs", import.meta.url), "utf8");
const payload = Buffer.from(JSON.stringify({ account: {
key: "PRIVATE-CREDENTIAL-SENTINEL", refresh_token: "PRIVATE-REFRESH-SENTINEL",
expires_at: new Date(input.expiry ?? Date.now() - 60_000).toISOString(),
expires_at: "rawExpiry" in input ? input.rawExpiry : new Date(input.expiry ?? Date.now() - 60_000).toISOString(),
} }));
const fs = {
constants,
@@ -2166,6 +2180,20 @@ describe("Grok launcher subscription refresh", () => {
const test = await fixture({ expiry: Date.now() + 600_000 }); test.run();
expect(test.spawnSync).not.toHaveBeenCalled(); expect(test.execve).toHaveBeenCalledOnce();
});
it.each(["seconds", "milliseconds"])("refreshes expired and near-expiry numeric %s but skips fresh credentials", async encoding => {
for (const [offset, expected] of [[-60_000, true], [30_000, true], [600_000, false]] as const) {
const ms = Date.now() + offset;
const test = await fixture({ rawExpiry: encoding === "seconds" ? ms / 1000 : ms });
test.run();
expect(test.spawnSync).toHaveBeenCalledTimes(expected ? 1 : 0);
expect(test.execve).toHaveBeenCalledOnce();
}
});
it.each([null, "1760000000", "2020-01-01", true, {}, []])("does not coerce unsupported expiry encodings: %j", async rawExpiry => {
const test = await fixture({ rawExpiry }); test.run();
expect(test.spawnSync).not.toHaveBeenCalled();
expect(test.execve).toHaveBeenCalledOnce();
});
it("never discovers subscription credentials for an explicit API key", async () => {
const test = await fixture({ apiKey: "explicit-api-key" }); test.run();
expect(test.fs.openSync).not.toHaveBeenCalled(); expect(test.spawnSync).not.toHaveBeenCalled(); expect(test.execve).toHaveBeenCalledOnce();
@@ -36,7 +36,7 @@ export const QUALIFIED_ACPX_PROFILES: Readonly<
acpxVersion: QUALIFIED_ACPX_VERSION, agent: "grok", agentProfileVersion: 1,
agentServerPackage: "@paperclipai/grok-acp", agentServerVersion: "1.0.13",
agentRuntimePackage: "@paperclipai/grok-acp", agentRuntimeVersion: "1.0.13",
commandDigest: "sha256:387d6a186753307fdf6f6d8898fa543525239312e31e2c5d5c4baa6b6eec6671",
commandDigest: "sha256:f0b698395a3704ed2ffaf84ea19bdb20c36c8a0a70b7c629c7b6ffe144e59e55",
qualificationModel: "grok-4.7", reportedModelId: "grok-4.7", permissionPolicy: "interactive",
},
pi: {
@@ -1074,7 +1074,7 @@ describe("remote provider pack manifest", () => {
distDigest: sha256DirectoryTree(join(root, "dist")),
bridgeDigest: "",
acpxProfileDigests: {
grok: "sha256:42fe296ec6fc0715c3509cec9671451bcd5bfdc7f185041101c8aac1e9ac8718",
grok: "sha256:f0b698395a3704ed2ffaf84ea19bdb20c36c8a0a70b7c629c7b6ffe144e59e55",
claude:
"sha256:9d73d1f0f121fb96cc8badb28c22d5bff02d8582eb2e40360a81c189e1b9422a",
codex:
@@ -9237,7 +9237,7 @@ const REMOTE_PROVIDER_PACK_PINS = {
grok: "1.0.13",
} as const;
const REMOTE_PROVIDER_PACK_PROFILE_DIGESTS = {
grok: "sha256:42fe296ec6fc0715c3509cec9671451bcd5bfdc7f185041101c8aac1e9ac8718",
grok: "sha256:f0b698395a3704ed2ffaf84ea19bdb20c36c8a0a70b7c629c7b6ffe144e59e55",
claude:
"sha256:9d73d1f0f121fb96cc8badb28c22d5bff02d8582eb2e40360a81c189e1b9422a",
codex: