refactor: trim bootstrap token metadata

This commit is contained in:
Peter Steinberger
2026-03-12 22:36:37 +00:00
parent 589aca0e6d
commit 1c7ca391a8
3 changed files with 18 additions and 26 deletions

View File

@@ -405,14 +405,7 @@ export default function register(api: OpenClawPluginApi) {
const payload: SetupPayload = {
url: urlResult.url,
bootstrapToken: (
await issueDeviceBootstrapToken({
channel: ctx.channel,
senderId: ctx.senderId ?? ctx.from ?? ctx.to,
accountId: ctx.accountId,
threadId: ctx.messageThreadId != null ? String(ctx.messageThreadId) : undefined,
})
).token,
bootstrapToken: (await issueDeviceBootstrapToken()).token,
};
if (action === "qr") {

View File

@@ -1,4 +1,4 @@
import { mkdtemp, rm } from "node:fs/promises";
import { mkdtemp, readFile, rm } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, describe, expect, it, vi } from "vitest";
@@ -95,4 +95,20 @@ describe("device bootstrap tokens", () => {
}),
).resolves.toEqual({ ok: false, reason: "bootstrap_token_invalid" });
});
it("persists only token state that verification actually consumes", async () => {
const baseDir = await createBaseDir();
const issued = await issueDeviceBootstrapToken({ baseDir });
const raw = await readFile(join(baseDir, "devices", "bootstrap.json"), "utf8");
const state = JSON.parse(raw) as Record<string, Record<string, unknown>>;
const record = state[issued.token];
expect(record).toMatchObject({
token: issued.token,
});
expect(record).not.toHaveProperty("channel");
expect(record).not.toHaveProperty("senderId");
expect(record).not.toHaveProperty("accountId");
expect(record).not.toHaveProperty("threadId");
});
});

View File

@@ -17,10 +17,6 @@ export type DeviceBootstrapTokenRecord = {
publicKey?: string;
roles?: string[];
scopes?: string[];
channel?: string;
senderId?: string;
accountId?: string;
threadId?: string;
issuedAtMs: number;
lastUsedAtMs?: number;
};
@@ -29,11 +25,6 @@ type DeviceBootstrapStateFile = Record<string, DeviceBootstrapTokenRecord>;
const withLock = createAsyncLock();
function normalizeOptionalString(value: string | undefined): string | undefined {
const trimmed = value?.trim();
return trimmed ? trimmed : undefined;
}
function mergeRoles(existing: string[] | undefined, role: string): string[] {
const out = new Set<string>(existing ?? []);
const trimmed = role.trim();
@@ -80,10 +71,6 @@ async function persistState(state: DeviceBootstrapStateFile, baseDir?: string):
export async function issueDeviceBootstrapToken(
params: {
channel?: string;
senderId?: string;
accountId?: string;
threadId?: string;
baseDir?: string;
} = {},
): Promise<{ token: string; expiresAtMs: number }> {
@@ -94,10 +81,6 @@ export async function issueDeviceBootstrapToken(
state[token] = {
token,
ts: issuedAtMs,
channel: normalizeOptionalString(params.channel),
senderId: normalizeOptionalString(params.senderId),
accountId: normalizeOptionalString(params.accountId),
threadId: normalizeOptionalString(params.threadId),
issuedAtMs,
};
await persistState(state, params.baseDir);