Docs

Authentication via Cuitty Safe

Scrape stores no secrets. The engine depends on a CredentialProvider, and the live integration can wrap @cuitty/safe/client through createSafeCredentialProvider(config).

Credential Provider

The provider surface is:

MethodPurpose
resolve(auth)Resolve safe-ref or safe-refs into values for the login flow.
writeSession(ref, storageState)Persist captured Playwright storage state.
readSession(ref)Hydrate a previously captured session.
health()Report ok, needs-auth, or unavailable.

Safe Provider

You can inject a Safe client for tests or let the provider lazy-load @cuitty/safe/client at runtime.

import { createSafeCredentialProvider, type SafeClientLike } from "@cuitty/scrape/auth/safe";

const safeClient = {
  secrets: {
    async read(ref: string) {
      return { value: ref === "safe://example/password" ? "s3cr3t" : undefined };
    },
    async write(ref: string, value: { value: string }) {
      console.log("stored", ref, value.value.length);
    },
  },
  async resolve(refs: string | string[]) {
    const list = Array.isArray(refs) ? refs : [refs];
    return {
      resolved: Object.fromEntries(list.map((ref) => [ref, "resolved-value"])),
      failures: [],
    };
  },
  async health() {
    return { providers: [{ status: "ok" }] };
  },
} satisfies SafeClientLike;

const credentials = createSafeCredentialProvider({ client: safeClient });
const resolved = await credentials.resolve({ kind: "safe-ref", ref: "safe://example/password" });

console.log(resolved.resolved.value);

Auth Reference Types

ScrapeAuthRef supports:

KindShapePurpose
none{ kind: "none" }No auth.
safe-ref{ kind: "safe-ref", ref }One credential value.
safe-refs{ kind: "safe-refs", refs }Named credentials for multi-field flows.
session{ kind: "session", sessionRef }Reuse captured storage state.

Session Capture

Set captureSessionAs on a request. After a successful run, the engine calls session.storageState() and persists it with credentials.writeSession(ref, state).

import { createScrapeServer } from "@cuitty/scrape/server";
import { createMockCredentialProvider } from "@cuitty/scrape/auth";

const credentials = createMockCredentialProvider();
const server = createScrapeServer({ credentials });

await server.run({
  url: "https://example.com",
  intent: "Read the page after login",
  captureSessionAs: "safe://sessions/example",
});

const saved = await credentials.readSession("safe://sessions/example");
console.log(Boolean(saved));

Session Reuse Flow

Use auth: { kind: "session", sessionRef } on later runs. The engine reads the stored state and calls session.hydrate(storageState) before navigation.