Types
These identifiers and small shared types appear across every namespace. They name a tenant, a device, a person, a role and the kind of client an application is.
Identifiers
type TenantId = string;type RecipientId = string;type Locator = string;type EventId = string;type Bytes = Uint8Array;type Seconds = number;typealias TenantId = Stringtypealias RecipientId = Stringtypealias Locator = Stringtypealias EventId = Stringtypealias Bytes = Datatypealias Seconds = TimeIntervaltypealias TenantId = Stringtypealias RecipientId = Stringtypealias Locator = Stringtypealias EventId = Stringtypealias Bytes = ByteArraytypealias Seconds = Duration| Name | Description |
|---|---|
TenantId | Immutable. Device certificates (cards), stored objects and evidence carry it. |
RecipientId | Sixteen bytes of SHA-256 over a device’s public key, base64url. Every part of the SDK names a device by it. |
Locator | The opaque id of a record, file, folder or key domain root, the same across versions. |
EventId | An access event, assigned by the Seald Healthcare Cloud. |
Bytes | Raw bytes. |
Seconds | A duration in seconds. |
Person
Person names a person as the identity provider names them. It never holds a name or an email address.
interface Person { iss: string; sub: string;}struct Person { let iss: String let sub: String}data class Person( val iss: String, val sub: String,)| Field | Type | Description |
|---|---|---|
iss | string | The identity provider’s issuer. |
sub | string | The person’s subject at that issuer. |
Group
Group names a group as the identity provider names it.
type Group = string;typealias Group = Stringtypealias Group = StringRole
Owner, Admin, Employee and Contractor are fixed. Any other name is a role the tenant created.
type Role = 'owner' | 'admin' | 'employee' | 'contractor' | string;typealias Role = String// fixed roles: "owner", "admin", "employee", "contractor"typealias Role = String// fixed roles: "owner", "admin", "employee", "contractor"A tenant can create its own role names. Role is a plain string on every platform rather than a closed enum. The four fixed roles are the string literals shown. Any other value is a role the tenant created.
Classification
type Classification = 'phi' | 'pii' | 'public' | 'de-identified';enum Classification { case phi, pii, `public`, deIdentified }enum class Classification { PHI, PII, PUBLIC, DE_IDENTIFIED }| Value | Description |
|---|---|
phi | Protected health information. |
pii | Personally identifiable information. |
public | No restriction. |
de-identified | Identifiers removed. |
ClientKind
type ClientKind = 'extension' | 'desktop' | 'mobile' | 'sdk';enum ClientKind { case `extension`, desktop, mobile, sdk }enum class ClientKind { EXTENSION, DESKTOP, MOBILE, SDK }| Value | Description |
|---|---|
extension | The browser extension. |
desktop | A desktop application. |
mobile | A mobile application. |
sdk | An AI agent or another integration built directly on the SDK. |
A tenant sets the version floor per kind. It applies at create and on every session.
Decided
Every call the tenant’s policies decide returns a Decided. It is one of three decisions:
allow, with what was asked fordeny, with its reasonchallenge, to sign in again
Every decision carries the EventId of its access event. Access decisions covers each decision and the allowed helper.
type Outcome = 'allow' | 'deny' | 'challenge';type Decided<T = {}> = Allowed<T> | Denied | Challenged<T>;enum Decided<T> { case allow(T, eventId: EventId) case deny(Denied) case challenge(Challenged<T>)}sealed interface Decided<out T> { data class Allow<T>(val value: T, val eventId: EventId) : Decided<T> data class Deny(val eventId: EventId, val reason: DenyReason, val text: String) : Decided<Nothing> class Challenge<T>(val eventId: EventId) : Decided<T> { suspend fun stepUp(): Decided<T> }}Denied
interface Denied { outcome: 'deny'; eventId: EventId; reason: DenyReason; text: string;}struct Denied { let eventId: EventId let reason: DenyReason let text: String}data class Deny(val eventId: EventId, val reason: DenyReason, val text: String) : Decided<Nothing>| Field | Type | Description |
|---|---|---|
eventId | EventId | The access event this decision recorded. |
reason | DenyReason | One of the fixed deny reasons. |
text | string | The fixed words the person sees. |
Challenged
interface Challenged<T> { outcome: 'challenge'; eventId: EventId; stepUp(): Promise<Decided<T>>;}struct Challenged<T> { let eventId: EventId func stepUp() async throws -> Decided<T>}class Challenge<T>(val eventId: EventId) : Decided<T> { suspend fun stepUp(): Decided<T>}| Field | Type | Description |
|---|---|---|
eventId | EventId | The access event this decision recorded. |
stepUp | () => Promise<Decided<T>> | Runs a fresh multi-factor sign-in through the sign-in adapter, then repeats the request. It returns a second decision with its own access event. |
Unsubscribe
type Unsubscribe = () => void;client.on returns an Unsubscribe in TypeScript. Call it to stop receiving that event. Swift represents the same subscription as an AsyncStream you stop by ending iteration. Kotlin represents it as a Flow you stop by canceling collection. Neither needs an Unsubscribe value of its own.
Card
A Card is a device certificate, signed by its tenant’s identity authority.
interface Card { recipientId: RecipientId; tenantId: TenantId; person: Person; issuedAt: Date; state: 'active' | 'superseded' | 'revoked'; replaces?: RecipientId;}struct Card { let recipientId: RecipientId let tenantId: TenantId let person: Person let issuedAt: Date let state: State let replaces: RecipientId?
enum State { case active, superseded, revoked }}data class Card( val recipientId: RecipientId, val tenantId: TenantId, val person: Person, val issuedAt: Instant, val state: State, val replaces: RecipientId?,) { enum class State { ACTIVE, SUPERSEDED, REVOKED }}| Field | Type | Description |
|---|---|---|
recipientId | RecipientId | The device this card certifies. |
tenantId | TenantId | The tenant it was issued in. |
person | Person | Whose device it is. |
issuedAt | date | When it was issued. |
state | "active", "superseded" or "revoked" | The card’s status, as the withdrawal feed reports it. A card that is no longer active locks the client that holds it. |
replaces | RecipientId, optional | The card this one replaces, for a replacement enrollment. |