Personas with provenance
A persona bundles roles at chosen scopes; assigning it writes ordinary memberships that remember which persona sustains them.
The situation
A production lead needs write access to packing and review, and read access to shipping. Every new lead needs the same set. When the job changes, the set should change for everyone holding it, without touching grants an admin made by hand.
The recipe
import { createClient } from '@hotmeshio/long-tail';
const lt = createClient({ auth: { userId: adminId } });
await lt.personas.seed([ { key: 'production-lead', title: 'Production lead', description: 'Works packing and review, watches shipping.', roles: [ { role: 'packing', relationship: 'write-all' }, { role: 'review', relationship: 'write-all' }, { role: 'shipping', relationship: 'read-all' }, ], },]);| relationship | read_scope | write_scope |
|---|---|---|
write-all |
all |
all |
write-self |
all |
self |
read-all |
all |
none |
Assign with POST /api/users/:id/personas, lt.personas.assign, ltc personas, or the assign_persona MCP tool. Each role brings its own pins, list schema and form schema, so one assignment composes the member’s whole dashboard.
The guarantee
Personas are not a second authorization path: assignment fans out to ordinary lt_user_roles rows. Each row carries granted_by_persona, so unassigning removes only the rows that persona sustains, and a row a sibling persona still grants is re-homed instead of removed. Highest allowance wins per role. The seed is idempotent and reconciles every current holder in the same transaction. See Identity.
Related patterns
Identity
Member scope profiles
Two scope axes on a membership give five profiles, from full worker to auditor, all enforced inside the query.
Forms and configuration
Pins are the bookmark set
A role ships the exact queries its members need as pinned views with live counts, in their nav from the first login.
Forms and configuration
Code-owned configuration
Set configSource to code and every declared role, workflow, topic, agent and scan scheme is diffed and applied on each boot from git.
