Jadpo is experimental and not ready for production. These docs follow the compiler's main branch as of 5 Nov 2026. What's built · Install 0.3.0
jadpo
ReferenceSign-in and identity

APIsSign-in and identity

The principal

On this page

The principal is whoever is calling, once Jadpo has checked them: either a user (a person) or a service (another system, such as a partner's server). You declare it once in app.jadpo, with no name. It says which stored record each kind of caller is. Here a signed-in person is a User, found by their email address:

app.jadpo:

example
use accounts/entities { User }application {}principal {    user: {        subject: User.email    }}

domains/accounts/entities/user.jadpo:

example
/// A person with an account.entity User {    id: Uuid    email: Email {        unique: true    }    policy: {        create: [Access.system]        read: [id]    }}

principal { } is built into Jadpo, as are Uuid, Email and Access. User is your app's own entity, a kind of stored record, and the use line brings it into app.jadpo from its file. create: [Access.system] lets only Jadpo itself create a user, the first time someone signs in, and read: [id] lets each user read only their own record.

This says who a person is. authentication { } says how they get in (Ways to sign in).

subject:

Jadpo needs to know which record a signed-in caller is. subject: names the field it finds them by, such as User.email or User.authentication_subject. The field must be unique. When your app has tenants (many organisations sharing one app, see Tenancy), it must be a field every tenant shares, so one person is one record. Jadpo looks the caller up by this field whenever it needs their current record.

active:

active: says when a record may still sign in. It is a condition on the same entity, written with its fields as a query's where: is, such as active: User.status == UserStatus.active. A caller whose record doesn't meet it is refused with user_disabled or service_disabled (see Sign-in failures). Leave it out and every record counts as active.

What code reads from the caller

The principal has three fields of its own, and no others:

  • id: the record's id, a User.id or a Service.id;
  • subject: the value of the subject: field;
  • strength: how the caller proved who they are, primary or multi_factor (How strongly a person signed in).

A role, a tenant or an email address isn't on the principal. Code that needs one reads it from the entity, which is where Policy reads it too.

Services

service: is optional, and most apps only have users. An app needs at least one of user: and service:. An app that other systems call says which record each of those is, beside its users:

app.jadpo:

example
use accounts/entities { Service, User }use accounts/types { ServiceStatus, UserStatus }application {}principal {    user: {        subject: User.email        active: User.status == UserStatus.active    }    service: {        subject: Service.name        active: Service.status == ServiceStatus.active    }}

User and Service are entities with a status field, and UserStatus and ServiceStatus are enums of your app's.

Markdown for agents: /docs/the-principal.md.Built from Jadpo main at aee2e8f.