Install
npm i @waterlock/gatewayNode 24+.
Quickstart
1. Gateway
The trusted side. It holds the Gmail credential:
import { serve } from "@hono/node-server";
import { createGateway, createSessions, staticToken } from "@waterlock/gateway";
import { gmail } from "@waterlock/gateway/providers/gmail";
const sessions = createSessions({ signingKey: process.env.WATERLOCK_SIGNING_KEY! }); // >= 32 bytes
const gateway = createGateway({
providers: [gmail({ credentials: staticToken({ token: process.env.GMAIL_ACCESS_TOKEN! }) })],
// Default deny: a call goes through only if an allow row matches and no deny row does.
policy: [
{
when: (r) =>
r.action === "gmail.users.messages.send" &&
r.context.recipients.length > 0 &&
r.context.recipients.every((addr) => addr === r.session.onBehalfOf),
reason: "You can only send email to yourself.",
},
],
sessions,
});
serve({ fetch: gateway.fetch, port: 8787 }); // gateway.fetch is (Request) => Response2. Session token
Minted for the agent, on the trusted side:
const { token } = await sessions.mint({ provider: "gmail", agent: "assistant", onBehalfOf: "alice@acme.com", ttlSeconds: 3600 });3. Harness
A stock client: the gateway as base URL, the session token as bearer.
import { auth, gmail } from "@googleapis/gmail";
const oauth = new auth.OAuth2();
oauth.setCredentials({ access_token: token });
const api = gmail({ version: "v1", auth: oauth, rootUrl: "http://127.0.0.1:8787/" });
await api.users.messages.send({ userId: "me", requestBody: { raw } });
// denied -> 403 { error: { code: "policy_denied", message: "You can only send email to yourself." } }Full runnable example: examples/ai-sdk-send-email.
Next: how calls map to rules in Actions, and the rule language in Policies.