Accept lowercase profile types and anchor sides when reading
This commit is contained in:
+6
-1
@@ -28,6 +28,11 @@ const VERDICTS = new Map<string, [event: string, mark: string]>([
|
||||
]);
|
||||
const PROFILE_TYPES = new Set<unknown>(["CLAUDE", "CODEX", "OPENCODE"]);
|
||||
const FAILURE_REASONS = new Set<unknown>(["SIGN_IN_FAILED", "USAGE_EXHAUSTED", "FAILED"]);
|
||||
// Anchors written before the UPPER_SNAKE switch spell sides in lowercase.
|
||||
const OLD_SIDES = new Map<unknown, Anchor["side"]>([
|
||||
["new", "NEW"],
|
||||
["old", "OLD"],
|
||||
]);
|
||||
const isProfileType = (value: unknown): value is ProfileFailure["type"] => PROFILE_TYPES.has(value);
|
||||
const isFailureReason = (value: unknown): value is FailureReason => FAILURE_REASONS.has(value);
|
||||
const failureComment = (failures: ProfileFailure[]): string =>
|
||||
@@ -56,7 +61,7 @@ function parseAnchors(text: string, sourcePath: string): Anchor[] {
|
||||
const path = field(entry, "path");
|
||||
const line = field(entry, "line");
|
||||
const givenSide = field(entry, "side");
|
||||
const side = givenSide === undefined ? "NEW" : givenSide;
|
||||
const side = givenSide === undefined ? "NEW" : (OLD_SIDES.get(givenSide) ?? givenSide);
|
||||
const body = field(entry, "body");
|
||||
if (typeof path !== "string" || path === "") {
|
||||
throw new TypeError(`${at}.path: expected a repository path`);
|
||||
|
||||
@@ -65,3 +65,14 @@ test("rejects malformed central credentials", async () => {
|
||||
),
|
||||
).rejects.toThrow("profiles[0].token");
|
||||
});
|
||||
|
||||
test("reads lowercase profile types from older credentials", async () => {
|
||||
const credentials = await parseCredentials(
|
||||
JSON.stringify({
|
||||
"reviewer-token": ENCRYPTED,
|
||||
profiles: [{ type: "codex" }, { type: "claude", token: ENCRYPTED }],
|
||||
}),
|
||||
MASTER_KEY,
|
||||
);
|
||||
expect(credentials.profiles.map(({ type }) => type)).toStrictEqual(["CODEX", "CLAUDE"]);
|
||||
});
|
||||
|
||||
@@ -78,6 +78,17 @@ export async function encryptCredential(
|
||||
return `v1:${encodeBase64Url(nonce)}:${encodeBase64Url(new Uint8Array(ciphertext))}`;
|
||||
}
|
||||
|
||||
// profiles.json files written before the UPPER_SNAKE switch spell types in lowercase.
|
||||
const OLD_PROFILE_TYPES = new Map<unknown, BotProfile["type"]>([
|
||||
["claude", "CLAUDE"],
|
||||
["codex", "CODEX"],
|
||||
["opencode", "OPENCODE"],
|
||||
]);
|
||||
|
||||
function currentSpelling(type: unknown): unknown {
|
||||
return OLD_PROFILE_TYPES.get(type) ?? type;
|
||||
}
|
||||
|
||||
async function parseProfile(entry: unknown, index: number, masterKey: string): Promise<BotProfile> {
|
||||
const at = `profiles[${index}]`;
|
||||
if (!isMapping(entry)) {
|
||||
@@ -88,7 +99,7 @@ async function parseProfile(entry: unknown, index: number, masterKey: string): P
|
||||
throw new Error(`${at}.${key}: unknown field`);
|
||||
}
|
||||
}
|
||||
const type = field(entry, "type");
|
||||
const type = currentSpelling(field(entry, "type"));
|
||||
const model = field(entry, "model");
|
||||
const token = field(entry, "token");
|
||||
if (type !== "CLAUDE" && type !== "CODEX" && type !== "OPENCODE") {
|
||||
|
||||
Reference in New Issue
Block a user