import { describe, expect, it } from "@suaveplan/testing/runner"; import { fileId, GrantManager, InMemoryPartitionStore, KeyRing, PartitionManager, TokenManager, TransferManager, userId, wrapKey, } from "../src/index.js"; import { getDefaultPolicy } from "../src/partitions/partition-policy/partition-policy.js"; describe("drive-sharing — end-to-end integration", () => { it("create partition, add member, grant access, transfer file", { timeout: 30000, }, async () => { // Build the full lifecycle stack with deterministic clocks / IDs. const events = new Map(); const bus = { on: () => () => undefined, emit: (k: string, p: unknown) => { const arr = events.get(k) ?? []; arr.push(p); events.set(k, arr); }, }; let counter = 0; const idGen = () => `id-${(counter += 1)}`; const masterKey = new Uint8Array(32).fill(0x77); const keyRing = new KeyRing({ masterKey }); const store = new InMemoryPartitionStore(); const partitions = new PartitionManager({ store, keyRing, clock: () => 1_000, idGenerator: idGen, events: bus, }); const grants = new GrantManager({ clock: () => 1_000, idGenerator: idGen, events: bus, }); const tokens = new TokenManager({ clock: () => 1_000, defaultTTL: 60_000, masterKey, idGenerator: idGen, }); // 1. Create source and target partitions. const src = await partitions.create({ name: "research", type: "shared", ownerId: userId("alice"), }); const dst = await partitions.create({ name: "review", type: "shared", ownerId: userId("alice"), }); // 2. Add bob as a member of source. const updatedSrc = await partitions.addMember(src.id, userId("bob"), { permissions: ["read", "share"], }); expect(updatedSrc.members.length).toBe(1); // 3. Mint a grant for bob to read the file. const grant = grants.create({ grantorId: userId("alice"), granteeId: userId("bob"), partitionId: src.id, permissions: ["read"], expiresAt: 5_000_000, }); const check = grants.check(grant.id, userId("bob"), "read"); expect(check.allowed).toBe(true); // 4. Mint a share token for the file. const token = tokens.create({ partitionId: src.id, createdBy: userId("alice"), permissions: ["read"], }); expect(tokens.validate(token.id).valid).toBe(true); // 5. Set up transfer with a real wrapped DEK. const sourceKek = new Uint8Array(32).fill(0xaa); const targetKek = new Uint8Array(32).fill(0xbb); const dek = new Uint8Array(32).fill(0xcc); const aadSrc = new TextEncoder().encode( `drive-sharing/v1/transfer/${src.id}/${fileId("f-1")}` ); const wrapped = await wrapKey(sourceKek, dek, { aad: aadSrc }); const transfer = new TransferManager({ kekResolver: async (_uid, pid) => pid === src.id ? sourceKek : targetKek, policyResolver: async (pid) => { const partition = pid === src.id ? updatedSrc : { ...dst, members: [] }; return { policy: getDefaultPolicy(), partition, }; }, wrappedKeyResolver: async () => wrapped, clock: () => 2_000, }); const result = await transfer.transfer({ fileId: fileId("f-1"), sourcePartitionId: src.id, targetPartitionId: dst.id, userId: userId("alice"), direction: "export", }); expect(result.success).toBe(true); expect(result.rewrappedKey).toBeDefined(); // 6. Verify lifecycle event emission. expect(events.get("partition:created")?.length).toBe(2); expect(events.get("member:added")?.length).toBe(1); expect(events.get("grant:created")?.length).toBe(1); // 7. Revoke the grant and confirm subsequent checks are denied. grants.revoke(grant.id); expect(grants.check(grant.id, userId("bob"), "read").allowed).toBe( false ); }); });