Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899import { describe, expect, it, vi } from "vitest";import type { OAuthUserAgent } from "@atcute/oauth-browser-client";import { mainSchema as addSecretSchema } from "$lib/api/lexicons/types/org/tangled/secret/addSecret";import { didOf, type Capability, type KnotOrigin } from "$lib/api/syntax";
const knot = "knot.test" as KnotOrigin;const minted = vi.hoisted(() => vi.fn());
vi.mock("$lib/auth/agent", () => ({ createClient: () => ({}), mintServiceAuth: async () => "user-token", serviceDidForHost: (host: string) => `did:web:${host}`, hostForServiceDid: () => null}));
vi.mock("$lib/api/knot", () => ({ knotCapabilities: async (asked: KnotOrigin) => asked === "knot.test" ? (["knot-repo-token-mint"] as unknown as readonly Capability[]) : null}));
vi.mock("$lib/api/cob", () => ({ knotProcedure: minted}));
const { spindleXrpc } = await import("$lib/api/spindlewrite");
const agent = { sub: "did:plc:nel" } as unknown as OAuthUserAgent;const target = { knot, repoDid: didOf("did:plc:repoproof") };
const stubbed = (body: unknown) => { const fetch = vi.fn<typeof globalThis.fetch>( async () => new Response(JSON.stringify(body), { status: 200 }) ); vi.stubGlobal("fetch", fetch); return fetch;};
describe("spindle write targets", () => { it("mints a repo token under the per-repo session when the knot advertises it", async () => { minted.mockResolvedValue({ token: "repo-token" }); const fetch = stubbed({}); const client = await spindleXrpc(agent, new URL("https://spindle.test"), target);
await client.call(addSecretSchema, { input: { repo: target.repoDid, key: "K", value: "v" } });
expect(minted).toHaveBeenCalledWith( agent, knot, target.repoDid, "org.tangled.repo.mintToken", { aud: "did:web:spindle.test", lxm: "org.tangled.secret.addSecret", exp: expect.any(Number) }, { signal: expect.any(AbortSignal), invalidate: false } ); const sent = new URL(String(fetch.mock.calls[0][0])); expect(sent.origin).toBe("https://spindle.test"); expect(sent.pathname).toBe("/xrpc/org.tangled.secret.addSecret"); expect(new Headers(fetch.mock.calls[0][1]?.headers).get("authorization")).toBe( "Bearer repo-token" ); });
it("uses user token when the knot lacks the cap or mint will fail", async () => { minted.mockClear(); const olderKnot = stubbed({}); const incapable = await spindleXrpc(agent, new URL("https://spindle.test"), { repoDid: target.repoDid, knot: "older-knot.test" as KnotOrigin }); await incapable.call(addSecretSchema, { input: { repo: target.repoDid, key: "K", value: "v" } }); expect(minted).not.toHaveBeenCalled(); expect(new Headers(olderKnot.mock.calls[0][1]?.headers).get("authorization")).toBe( "Bearer user-token" );
minted.mockImplementation(() => { throw new Error("Exp too far in the future."); }); const failing = stubbed({}); const client = await spindleXrpc(agent, new URL("https://spindle.test"), target); await client.call(addSecretSchema, { input: { repo: target.repoDid, key: "K", value: "v" } }); expect(minted).toHaveBeenCalledTimes(1); expect(new Headers(failing.mock.calls[0][1]?.headers).get("authorization")).toBe( "Bearer user-token" ); });});