Skip to main content

Model entities

Building a connector, step 3 of 10. Previous: Discover the target system.

Entities are the objects in the system that Owlie tracks. Exactly one of them is the account, the object Owlie links to an identity and provisions. The others are objects that access is granted on (groups, roles, workspaces), objects that hold access themselves, and objects that other records point to. This page covers choosing them, identifying them and describing their records. The next page maps access between them.

Choose the entities​

An entity is an object with a stable identity that Owlie needs to know about:

  • the account;
  • objects that are the target of access: a group, a role, a workspace, a project;
  • objects that hold access themselves: a group that is a member of another group;
  • lookup objects that records refer to: an organizational unit, a department.

Do not make an entity out of an assignment. A role that exists as an object in the system is an entity. "Role X in project Y" is a Grant with a qualifier, not a third entity. Reuse one entity wherever the same object appears: a group that is both a membership target and a holder of folder access is one group entity, not two.

Entity keys are singular and lowercase: user, group, role, org_unit. The keys grant, grants, connection and notification are reserved. Once a connector version is published, its entity keys are part of what installs depend on, so choose them carefully.

The account entity​

Exactly one entity is the account. Humans, service accounts and bots are all records of that one entity; Owlie has no second account entity. Map the system's account states onto Owlie's three lifecycle states:

Owlie stateMeansTypical system states
ACTIVEThe account can sign in.active, enabled
DISABLEDThe account exists but cannot sign in.suspended, deactivated, blocked, locked
DELETEDThe account is gone or soft-deleted.deleted, archived

Two account shapes need a declaration:

  • Invitations. When creating an account sends an invitation and the account becomes real only when the person accepts, declare create_semantics: "invite". Owlie shows the account as pending until it is accepted.
  • Accounts created elsewhere. When something other than this connector creates the accounts (another connector, or single sign-on the first time someone signs in) and this connector should only manage their access, declare create_semantics: "external". Owlie then waits for Sync to find the account before adding Grants, and never creates, disables or deletes it. This is a Grants-only connector.

In the connector builder, set this on the account entity's Details tab under Account creation. Choosing invitations there also offers the re-invite operation, the invite expiry attribute, and whether the account's id changes when the invitation is accepted.

Identifiers​

Mark each identifier property with "x-identifier": true, and list the same property names, first one first, in the entity's identifier_paths. When identifier_paths is present it decides the order, whatever order the properties are declared in, so always declare it. The first identifier is the entity's external id. Owlie keys the record by it forever, and every relationship must name the entity by that same value. Later identifiers are for lookups and matching.

Owlie reads the external id from the first identifier that has a value in the record. If the first is missing or empty on a record, the next identifier keys it instead, and Owlie sees a different record from the one it knew. Make sure the first identifier is present on every record your connector returns.

Choose the system's opaque, immutable id first. An email address or username that can change must never be the first identifier: when it changes, Owlie would see a new account and lose the old one's history. When the vendor documents that an id is never changed or reused, also mark it "x-provider-stable-id": true.

Describe the records​

Each entity has a JSON Schema describing the record exactly as the system returns it. Return the system's data as it is; never reshape it into an Owlie format. Anything provisioning writes must be a top-level property. Annotate properties to tell provisioning how to treat them:

AnnotationUse it for
readOnly: trueValues the system sets, such as ids and timestamps. Never written.
writeOnly: trueValues sent but never read back, such as a password.
"x-sensitive": trueSecrets and personal data to mask in logs. Not allowed on a property marked x-provider-stable-id, or on one that an x-reference points at.
"x-provisioning": { "requiredOn": ["PROVISION"] }Required only when creating an account.
"x-provisioning": { "writableOn": ["PROVISION"] }Can be set at creation only.
"x-provisioning": { "immutable": true }Set once, rejected on later updates.
"x-reference": { "entity": "user", "attribute": "id" }A property that points at another account, such as a manager.

Declare sync_support.supports_incremental: true only when the system has a reliable "changed since" query. Every field an entity can carry is in Connector manifest. Engine-based kinds (LDAP, SCIM, SQL, flat file) generate these schemas from their definitions; you still make the same decisions there.

Write it down​

Before moving on, list each entity with its key, what it is in the system, whether it is the account, its first identifier and the call that lists it.

Next: Model Grant kinds