Skip to content

Native principal

Your Express session middleware, Fastify JWT plugin, or Hono auth middleware already knows who the caller is. By default Arc ignores that and runs its own authentication handlers. When you want Arc to use the host’s verified user instead, switch on the native principal mode and hand the principal over explicitly.

Set nativePrincipal: true in the options, and pass a callback as the second argument to cratisArc. The callback runs for every Arc request and returns a NativeRequestContext:

server.ts
import express from 'express';
import { ArcApplication, type Principal } from '@cratis/arc.core';
import { cratisArc } from '@cratis/arc.express';
// Your own session middleware sets request.user after verifying the session.
type SessionRequest = express.Request & { user?: { id: string; roles: string[] } };
const builder = ArcApplication.createBuilder({ nativePrincipal: true });
await builder.discover(new URL('./Features/', import.meta.url));
const arc = await builder.build();
const app = express();
// app.use(yourVerifiedSessionMiddleware);
app.use(cratisArc(arc, request => {
const user = (request as SessionRequest).user;
const principal: Principal | undefined = user ? { ...user, isAuthenticated: true } : undefined;
return { principal };
}));

The session middleware in this example is yours. Arc does not implement or validate session cookies: host sessions can use HttpOnly, Secure, and SameSite cookies according to your framework’s own middleware.

PropertyMeaning
principalThe host-verified caller; used only when nativePrincipal is on
secureWhether the connection is TLS; Express and Fastify take it from the Node TLS socket unless you override it
authorityA host name known from trusted configuration, not the request Host header; used by the subdomain tenant source
remoteAddressThe caller’s address, for anonymous per-caller observable limits

The callback can be async. Adapters invoke it inside Arc’s error boundary, so a thrown error becomes a redacted 500 with a correlation ID and a logger call.

  • nativePrincipal: true cannot be combined with Arc authentication handlers; the server refuses to start with both.
  • For an operation that requires a named scheme, the callback must supply a principal carrying that scheme.
  • WebSocket upgrades take their own callback; see WebSockets.
  • The standalone Node host takes the same callback as its native option; see Arc.Core.
  • server.handle(request, native) accepts the same context, or an async callback returning it, for Fetch API hosts. This is a privileged, server-side seam.