The principal
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:
use accounts/entities { User }application {}principal { user: { subject: User.email }}
domains/accounts/entities/user.jadpo:
/// 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'sid, aUser.idor aService.id;subject: the value of thesubject:field;strength: how the caller proved who they are,primaryormulti_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:
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.