mirror of
https://github.com/hanzoai/sign.git
synced 2026-10-21 01:21:51 +00:00
The socket the app's pages call over (/zap) opened only for a session, so a recipient signing by their link, who has no account, could not reach the routes that sign a field or complete a document: every field they clicked failed with "An error occurred while signing the field". tRPC had served those as public procedures; the port to ZAP kept their bodies and lost the door. A connection from the app's own pages with no session now opens as anonymous and reaches only the routes tRPC served publicly, each authorised by the token it carries; every other route answers it 401 before its handler runs. The operation API still refuses a request without a token.
54 lines
2.0 KiB
TypeScript
54 lines
2.0 KiB
TypeScript
// esign ZAP RPC — per-connection context.
|
|
//
|
|
// The minted context the ZAP server threads into every handler. It is the
|
|
// subset of the tRPC `TrpcContext` the migrated handlers actually consume:
|
|
// the authenticated user, the (optional) session, the resolved teamId, the
|
|
// request metadata, and a logger. Auth is established ONCE at the WebSocket
|
|
// upgrade (see mint.ts), exactly like tRPC's authenticatedMiddleware ran per
|
|
// request — the difference is the ZAP context is per-connection, set when the
|
|
// socket opens.
|
|
import type { Session } from '@prisma/client';
|
|
import type { Logger } from 'pino';
|
|
|
|
import type { ApiRequestMetadata } from '@hanzo/esign-lib/universal/extract-request-metadata';
|
|
|
|
/**
|
|
* The authenticated principal common to both auth paths. Session auth yields a
|
|
* full SessionUser and API-token auth yields the narrower apiToken.user select;
|
|
* the migrated handlers only read id/name/email, the intersection of the two,
|
|
* mirroring what tRPC's `ctx.user` exposed across its session/api branches.
|
|
*/
|
|
export interface ZapUser {
|
|
id: number;
|
|
name: string | null;
|
|
email: string;
|
|
}
|
|
|
|
/**
|
|
* A connection opened without a session, from the app's own pages: a recipient
|
|
* signing by the token in their link, a visitor on a direct template link. It
|
|
* reaches only the routes in `publicRoutes` (routes.ts), each authorised by the
|
|
* token it carries, exactly as tRPC served them as public procedures.
|
|
*/
|
|
export interface AnonymousZapContext {
|
|
user: null;
|
|
session: null;
|
|
teamId: -1;
|
|
metadata: ApiRequestMetadata;
|
|
logger: Logger;
|
|
}
|
|
|
|
/** What a connection is minted as: signed in, or anonymous. */
|
|
export type ZapConnectionContext = ZapContext | AnonymousZapContext;
|
|
|
|
/** Authenticated per-connection context for ZAP handlers. */
|
|
export interface ZapContext {
|
|
user: ZapUser;
|
|
/** Present for session auth, null for API-token auth (mirrors tRPC). */
|
|
session: Session | null;
|
|
/** Resolved team id; -1 when a session has no team (tRPC convention). */
|
|
teamId: number;
|
|
metadata: ApiRequestMetadata;
|
|
logger: Logger;
|
|
}
|