__tests__/device-token.test.js
Rama main · réplica de lectura del repositorio original.
/**
* A durable device login: minted once behind the owner's sign-in, it joins the same keys map the bearer
* auth checks (so it resolves to the owner, console:true), survives a restart via its file, rotates on
* re-enrol, and revokes per device. No server, no cluster — the module against a temp file.
*/
import { describe, it, expect, beforeEach } from 'vitest';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
let dt; let dir;
beforeEach(async () => { dir = fs.mkdtempSync(path.join(os.tmpdir(), 'dt-')); process.env.PROFILE_DIR = dir; dt = await import('../src/deviceTokens.js?' + Math.random()); });
describe('durable device login', () => {
it('mints an owner-scoped token that resolves like the console, and persists it', () => {
const keys = new Map();
const rec = dt.mint(keys, { owner: 'carla', deviceId: 'fold', name: 'Carla Fold' });
expect(rec.token).toMatch(/^gbd_[0-9a-f]{48}$/);
const entry = keys.get(rec.token);
expect(entry).toMatchObject({ owner: 'carla', console: true, device: true, deviceId: 'fold', name: 'Carla Fold', plan: 'device' });
expect(entry.maxConcurrent).toBe(3);
// persisted to disk, and never the raw token in the owner's device list
expect(fs.existsSync(dt.FILE())).toBe(true);
expect(dt.list('carla')).toEqual([{ deviceId: 'fold', name: 'Carla Fold', createdAt: rec.createdAt }]);
expect(JSON.stringify(dt.list('carla'))).not.toContain(rec.token);
});
it('load() brings persisted tokens back into a fresh keys map after a restart', () => {
const rec = dt.mint(new Map(), { owner: 'carla', deviceId: 'fold' });
const keys2 = new Map(); expect(dt.load(keys2)).toBe(1);
expect(keys2.get(rec.token)).toMatchObject({ owner: 'carla', console: true });
});
it('re-enrolling the same device rotates the token (the old one stops working)', () => {
const keys = new Map();
const a = dt.mint(keys, { owner: 'carla', deviceId: 'fold' });
const b = dt.mint(keys, { owner: 'carla', deviceId: 'fold' });
expect(b.token).not.toBe(a.token);
expect(keys.has(a.token)).toBe(false); expect(keys.has(b.token)).toBe(true);
expect(dt.list('carla').length).toBe(1);
});
it('revoke removes one device, owner-scoped, and only that owner\'s', () => {
const keys = new Map();
const a = dt.mint(keys, { owner: 'carla', deviceId: 'fold' });
dt.mint(keys, { owner: 'carla', deviceId: 'laptop' });
dt.mint(keys, { owner: 'someone', deviceId: 'fold' });
expect(dt.revoke(keys, 'carla', 'fold')).toBe(1);
expect(keys.has(a.token)).toBe(false);
expect(dt.list('carla').map((d) => d.deviceId)).toEqual(['laptop']);
expect(dt.revoke(keys, 'carla', 'nope')).toBe(0);
expect(dt.list('someone').length).toBe(1); // another owner's device untouched
});
});