refactor: trim bootstrap token metadata
This commit is contained in:
@@ -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") {
|
||||
|
||||
@@ -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");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user