objects
client.objects opens records and files, saves new versions, creates objects and deletes them. Every call is one decision: allow, deny or challenge. Each decision records one access event.
open
open opens one object. It gets one decision and one access event. The plaintext is in the returned value. Under an offline lease, open returns the copy the offline lease covers.
open(ref: ObjectRef, options?: { action?: OpenAction }): Promise<Decided<Opened>>func open(_ ref: ObjectRef, action: OpenAction = .view) async throws -> Decided<Opened>suspend fun open(ref: ObjectRef, action: OpenAction = OpenAction.VIEW): Decided<Opened>Parameters
| Name | Type | Description |
|---|---|---|
ref | ObjectRef | The locator, and the version if not the current one. |
action | OpenAction, optional, default view | What the open is for: viewing, an access record, or downloading a file. |
Returns: Decided<Opened>: on allow, the open record or file.
Records: View, Access Record or Download File, as the action option says.
Errors: locked, no-session, unreachable if the stored object cannot be fetched and no offline lease covers it, storage-unreachable, container-invalid, trust-failed.
openField
openField opens one field alone. It uses that field’s key and nothing else.
openField(ref: ObjectRef, field: string): Promise<Decided<OpenedField>>func openField(_ ref: ObjectRef, field: String) async throws -> Decided<OpenedField>suspend fun openField(ref: ObjectRef, field: String): Decided<OpenedField>Parameters
| Name | Type | Description |
|---|---|---|
ref | ObjectRef | The locator, and the version if not the current one. |
field | string | The field name. |
Returns: Decided<OpenedField>: on allow, that one field’s value.
Records: View Field.
Errors: locked, no-session, unreachable, storage-unreachable, container-invalid, trust-failed.
save
save saves the next version of an object. It retries on its own if another save in the key domain lands first. If the object itself has a newer version, it returns BaseMoved.
save(locator: Locator, content: RecordContent | FileContent, options: SaveOptions): Promise<Decided<SaveOutcome> | Drafted>func save(_ locator: Locator, content: ObjectContent, baseVersion: Int, subject: String? = nil) async throws -> SaveResult<SaveOutcome>suspend fun save(locator: Locator, content: ObjectContent, baseVersion: Int, subject: String? = null): SaveResult<SaveOutcome>Parameters
| Name | Type | Description |
|---|---|---|
locator | Locator | The object to save a new version of. |
content | RecordContent | FileContent | The plaintext to save. |
options | SaveOptions | The version the edit was made from, and the subject identifier for a record. In Swift and Kotlin, baseVersion and subject are trailing labeled parameters instead. |
Returns: Decided<SaveOutcome> \| Drafted. Check 'outcome' in result in TypeScript. In Swift and Kotlin, check the SaveResult<SaveOutcome> case. On allow, a Saved, or a BaseMoved with the choice if the base moved. If the Seald Healthcare Cloud is unreachable, a Drafted locked to the device key.
Records: Save.
Errors: locked, no-session, storage-unreachable, container-invalid.
create
create creates a new object in a folder. The Seald Healthcare Cloud assigns a random locator. The new object’s version is 1.
create(folder: Locator, content: RecordContent | FileContent, options?: CreateOptions): Promise<Decided<Saved> | Drafted>func create(_ folder: Locator, content: ObjectContent, subject: String? = nil) async throws -> SaveResult<Saved>suspend fun create(folder: Locator, content: ObjectContent, subject: String? = null): SaveResult<Saved>Parameters
| Name | Type | Description |
|---|---|---|
folder | Locator | The folder the new object is created in. |
content | RecordContent | FileContent | The plaintext to save. |
options | CreateOptions, optional | The subject identifier for a record. In Swift and Kotlin, subject is a trailing labeled parameter instead. |
Returns: Decided<Saved> \| Drafted.
Records: Save.
Errors: locked, no-session, storage-unreachable, container-invalid.
acceptPending
acceptPending makes an AI agent’s pending version current. It counts as the delegator’s own save. Only the delegator may call it.
acceptPending(ref: Required<ObjectRef>): Promise<Decided<Saved>>func acceptPending(_ ref: ObjectRef) async throws -> Decided<Saved>suspend fun acceptPending(ref: ObjectRef): Decided<Saved>Parameters
| Name | Type | Description |
|---|---|---|
ref | ObjectRef, version required | The pending version to accept. |
Returns: Decided<Saved>.
Records: Save.
Who may call it: Only the agent’s delegator.
Errors: locked, no-session, not-found.
rejectPending
rejectPending leaves the pending version out of use for good. It never becomes current.
rejectPending(ref: Required<ObjectRef>): Promise<Decided<{}>>func rejectPending(_ ref: ObjectRef) async throws -> Decided<Void>suspend fun rejectPending(ref: ObjectRef): Decided<Unit>Parameters
| Name | Type | Description |
|---|---|---|
ref | ObjectRef, version required | The pending version to reject. |
Returns: Decided<{}>.
Records: One decision and one access event.
Who may call it: Only the agent’s delegator.
Errors: locked, no-session, not-found.
delete
delete retires a version, or every version of an object, into the recycle bin.
delete(ref: ObjectRef): Promise<Decided<{}>>func delete(_ ref: ObjectRef) async throws -> Decided<Void>suspend fun delete(ref: ObjectRef): Decided<Unit>Parameters
| Name | Type | Description |
|---|---|---|
ref | ObjectRef | The object, or one version of it, to retire. With no version named, it retires every version. |
Returns: Decided<{}>.
Records: Delete.
Who may call it: A domain owner only. The SDK refuses it under a legal hold or the dataset’s retention floor.
Errors: locked, no-session.
Types
ObjectKind
type ObjectKind = 'record' | 'file';enum ObjectKind: String { case record, file }enum class ObjectKind { RECORD, FILE }| Value | Meaning |
|---|---|
record | Structured fields, such as an encounter. |
file | Bytes with a name and a media type, such as a DICOM study. |
ObjectRef
interface ObjectRef { locator: Locator; version?: number;}struct ObjectRef { let locator: Locator var version: Int? = nil}data class ObjectRef(val locator: Locator, val version: Int? = null)| Field | Type | Description |
|---|---|---|
locator | Locator | The object’s opaque id, the same across versions. |
version | number, optional | The current version unless the person chose an earlier one. |
FieldValue
A record field’s value: what the customer’s row or document holds.
type FieldValue = string | number | boolean | null | FieldValue[] | { [field: string]: FieldValue };indirect enum FieldValue { case string(String), number(Double), boolean(Bool), null case array([FieldValue]), object([String: FieldValue])}sealed interface FieldValue { data class StringValue(val value: String) : FieldValue data class NumberValue(val value: Double) : FieldValue data class BooleanValue(val value: Boolean) : FieldValue object Null : FieldValue data class ArrayValue(val value: List<FieldValue>) : FieldValue data class ObjectValue(val value: Map<String, FieldValue>) : FieldValue}Any JSON-shaped value: a string, a number, a boolean, null, an array of field values, or a nested object of field values.
RecordContent
interface RecordContent { kind: 'record'; name: string; fields: { [field: string]: FieldValue };}struct RecordContent { let name: String let fields: [String: FieldValue]}data class RecordContent(val name: String, val fields: Map<String, FieldValue>) : ObjectContent| Field | Type | Description |
|---|---|---|
kind | 'record' | The tag that makes this a RecordContent. |
name | string | The record’s name, such as Visit note. |
fields | { [field: string]: FieldValue } | The record’s fields, by name. |
FileContent
interface FileContent { kind: 'file'; name: string; type: string; bytes: Bytes | ReadableStream<Bytes>; size?: number;}struct FileContent { let name: String let type: String let bytes: AsyncThrowingStream<Data, Error> var size: Int? = nil}data class FileContent( val name: String, val type: String, val bytes: Flow<ByteArray>, val size: Long? = null,) : ObjectContent| Field | Type | Description |
|---|---|---|
kind | 'file' | The tag that makes this a FileContent. |
name | string | The file’s name. |
type | string | A media type. |
bytes | Bytes | ReadableStream<Bytes> | The file’s content, in memory or streamed. |
size | number, optional | The file’s size in bytes, where known ahead of streaming. |
ObjectContent
type ObjectContent = RecordContent | FileContent;enum ObjectContent { case record(RecordContent) case file(FileContent)}sealed interface ObjectContentWhat save and create take: a RecordContent or a FileContent. In Swift, wrap the value in .record(...) or .file(...). In Kotlin, RecordContent and FileContent implement ObjectContent directly. Pass either one as is.
SaveOptions
interface SaveOptions { baseVersion: number; subject?: string;}struct SaveOptions { let baseVersion: Int var subject: String? = nil}data class SaveOptions(val baseVersion: Int, val subject: String? = null)| Field | Type | Description |
|---|---|---|
baseVersion | number | The version the edit was made from. |
subject | string, optional | The customer’s own identifier for the subject, such as a medical record number. The SDK tokenizes it into the subject ref under the tenant’s tokenization key. It never sends the identifier. For a record, if subject is absent, the SDK uses the dataset’s subject field. |
CreateOptions
interface CreateOptions { subject?: string;}struct CreateOptions { var subject: String? = nil}data class CreateOptions(val subject: String? = null)| Field | Type | Description |
|---|---|---|
subject | string, optional | The customer’s own identifier for the subject. |
Saved
interface Saved { kind: 'saved'; locator: Locator; version: number; pending: boolean;}struct Saved { let locator: Locator let version: Int let pending: Bool}data class Saved(val locator: Locator, val version: Int, val pending: Boolean)| Field | Type | Description |
|---|---|---|
kind | 'saved' | The tag that makes this a Saved. |
locator | Locator | The object’s locator. |
version | number | The version just saved. |
pending | boolean | An AI agent’s version, written but not current until its delegator calls acceptPending. |
BaseMoved
The version the edit was made from is no longer current. The SDK encrypts nothing until the person chooses.
interface BaseMoved { kind: 'base-moved'; currentVersion: number; saveAnyway(): Promise<Saved>; abandon(): void;}struct BaseMoved { let currentVersion: Int func saveAnyway() async throws -> Saved func abandon()}class BaseMoved(val currentVersion: Int) { suspend fun saveAnyway(): Saved fun abandon()}| Field | Type | Description |
|---|---|---|
kind | 'base-moved' | The tag that makes this a BaseMoved. |
currentVersion | number | The version that is now current. |
saveAnyway | () => Promise<Saved> | Saves as the next version anyway. The saved object and its access event record the version it was made from. |
abandon | () => void | Saves nothing. Your application may open the current version and carry the changes over. |
Drafted
The Seald Healthcare Cloud is unreachable. The SDK keeps the edit as a draft, locked to the device key, until the Seald Healthcare Cloud is back.
interface Drafted { kind: 'draft'; draftId: string;}struct Drafted { let draftId: String}data class Drafted(val draftId: String)| Field | Type | Description |
|---|---|---|
kind | 'draft' | The tag that makes this a Drafted. |
draftId | string | The draft’s id, for offline.discardDraft or shown among offline.drafts(). |
SaveOutcome
type SaveOutcome = Saved | BaseMoved;enum SaveOutcome { case saved(Saved) case baseMoved(BaseMoved)}sealed interface SaveOutcome { data class Saved(val saved: com.sealdhealthcare.sdk.Saved) : SaveOutcome data class BaseMoved(val baseMoved: com.sealdhealthcare.sdk.BaseMoved) : SaveOutcome}The allow payload of save: either the save went through as Saved, or the base moved and BaseMoved asks the person to choose.
SaveResult
What save and create return in Swift and Kotlin: a decision once the Seald Healthcare Cloud answers, or a draft while it is unreachable. TypeScript returns the union Decided<...> | Drafted. Check 'outcome' in result.
// inline in TypeScript:Decided<SaveOutcome> | Draftedenum SaveResult<T> { case decided(Decided<T>) case draft(Drafted)}sealed interface SaveResult<out T> { data class Decided<T>(val decided: com.sealdhealthcare.sdk.Decided<T>) : SaveResult<T> data class Draft(val drafted: Drafted) : SaveResult<Nothing>}OpenAction
type OpenAction = 'view' | 'access-record' | 'download-file';enum OpenAction: String { case view, accessRecord = "access-record", downloadFile = "download-file" }enum class OpenAction { VIEW, ACCESS_RECORD, DOWNLOAD_FILE }| Value | Meaning |
|---|---|
view | An ordinary open, for viewing. |
access-record | An open to give the record’s subject a copy. |
download-file | An open to download the file. |
FurtherAction
type FurtherAction = 'copy' | 'print' | 'download-file' | 'access-record';enum FurtherAction: String { case copy, print, downloadFile = "download-file", accessRecord = "access-record" }enum class FurtherAction { COPY, PRINT, DOWNLOAD_FILE, ACCESS_RECORD }| Value | Meaning |
|---|---|
copy | Copying what is open. |
print | Printing what is open. |
download-file | Downloading the open file. |
access-record | Giving the record’s subject a copy of what is open. |
Times
When an object was created and when a version was saved. TypeScript writes it inline as { created: Date; saved: Date } on OpenedBase and on the folders page’s Entry.
times: { created: Date; saved: Date };let times: (created: Date, saved: Date)data class Times(val created: Instant, val saved: Instant)| Field | Type | Description |
|---|---|---|
created | Date | When the object was created. |
saved | Date | When this version was saved. |
OpenedBase
The fields and methods every open shares, whether a record or a file.
interface OpenedBase { locator: Locator; version: number; kind: ObjectKind; name: string; type: string; size: number; times: { created: Date; saved: Date }; baseVersion?: number; pending: boolean; writer: RecipientId; epoch: number; offline: boolean; request(action: FurtherAction): Promise<Decided<{}>>; close(): void;}protocol OpenedBase { var locator: Locator { get } var version: Int { get } var kind: ObjectKind { get } var name: String { get } var type: String { get } var size: Int { get } var times: (created: Date, saved: Date) { get } var baseVersion: Int? { get } var pending: Bool { get } var writer: RecipientId { get } var epoch: Int { get } var offline: Bool { get } func request(_ action: FurtherAction) async throws -> Decided<Void> func close()}interface OpenedBase { val locator: Locator val version: Int val kind: ObjectKind val name: String val type: String val size: Int val times: Times val baseVersion: Int? val pending: Boolean val writer: RecipientId val epoch: Int val offline: Boolean suspend fun request(action: FurtherAction): Decided<Unit> fun close()}| Field | Type | Description |
|---|---|---|
locator | Locator | The object’s locator. |
version | number | The version that was opened. |
kind | ObjectKind | Whether this is a record or a file. |
name | string | The object’s name, fixed when it was saved. Storage cannot change it. |
type | string | The object’s media type, fixed when it was saved. |
size | number | The object’s size, fixed when it was saved. |
times | { created, saved } | When the object was created and when this version was saved, fixed when it was saved. |
baseVersion | number, optional | The version this one was saved from, where it is not the first. |
pending | boolean | An AI agent’s version, written but not current until its delegator accepts it. |
writer | RecipientId | The device that saved this version. |
epoch | number | The key domain epoch that protects this version. |
offline | boolean | True under an offline lease. The decision was made when the offline lease was granted. |
request | (action: FurtherAction) => Promise<Decided<{}>> | A further action on what is open, such as Copy or Print from the surface. It gets its own decision and access event. On allow, your application carries it out with the plaintext it already holds. |
close | () => void | Discards the plaintext and every key of this open. |
OpenedRecord
interface OpenedRecord extends OpenedBase { kind: 'record'; fields: { [field: string]: FieldValue }; masked: { field: string; reason: DenyReason; text: string }[];}struct OpenedRecord: OpenedBase { // OpenedBase's fields, plus: let fields: [String: FieldValue] let masked: [(field: String, reason: DenyReason, text: String)]}data class OpenedRecord( // OpenedBase's fields, plus: val fields: Map<String, FieldValue>, val masked: List<MaskedField>,) : OpenedBase| Field | Type | Description |
|---|---|---|
kind | 'record' | The tag that makes this an OpenedRecord. |
fields | { [field: string]: FieldValue } | The record’s fields. |
masked | { field, reason, text }[] | Fields the policies denied even though the object opened. Your application shows them masked, with the reason. |
OpenedFile
interface OpenedFile extends OpenedBase { kind: 'file'; bytes(): Promise<Bytes>; stream(): ReadableStream<Bytes>;}struct OpenedFile: OpenedBase { // OpenedBase's fields, plus: func bytes() async throws -> Data func stream() -> AsyncThrowingStream<Data, Error>}class OpenedFile(/* OpenedBase's fields */) : OpenedBase { suspend fun bytes(): ByteArray fun stream(): Flow<ByteArray>}| Field | Type | Description |
|---|---|---|
kind | 'file' | The tag that makes this an OpenedFile. |
bytes | () => Promise<Bytes> | The whole file, in memory. |
stream | () => ReadableStream<Bytes> | The file, streamed. |
Opened
type Opened = OpenedRecord | OpenedFile;enum Opened { case record(OpenedRecord) case file(OpenedFile)}
extension Opened: OpenedBase { // Forwards every OpenedBase member to the case's value: // locator, version, kind, name, type, size, times, baseVersion, // pending, writer, epoch, offline, request(_:), close()}sealed interface Opened : OpenedBase { data class Record(val record: OpenedRecord) : Opened, OpenedBase by record data class File(val file: OpenedFile) : Opened, OpenedBase by file}The allow payload of open: either an OpenedRecord or an OpenedFile, told apart by kind. In every language an Opened is itself an OpenedBase. opened.version, opened.request(...) and opened.close() work whichever kind it is. The members of one kind go through its case: in Swift case .record(let record): record.fields, in Kotlin is Opened.Record -> opened.record.fields and is Opened.File -> opened.file.stream().
OpenedField
interface OpenedField { locator: Locator; version: number; field: string; value: FieldValue; close(): void;}struct OpenedField { let locator: Locator let version: Int let field: String let value: FieldValue func close()}class OpenedField( val locator: Locator, val version: Int, val field: String, val value: FieldValue,) { fun close()}| Field | Type | Description |
|---|---|---|
locator | Locator | The object the field belongs to. |
version | number | The version that was opened. |
field | string | The field name. |
value | FieldValue | The field’s plaintext value. |
close | () => void | Discards the plaintext and every key of this open. |
Objects
interface Objects { open(ref: ObjectRef, options?: { action?: OpenAction }): Promise<Decided<Opened>>; openField(ref: ObjectRef, field: string): Promise<Decided<OpenedField>>; save(locator: Locator, content: RecordContent | FileContent, options: SaveOptions): Promise<Decided<SaveOutcome> | Drafted>; create(folder: Locator, content: RecordContent | FileContent, options?: CreateOptions): Promise<Decided<Saved> | Drafted>; acceptPending(ref: Required<ObjectRef>): Promise<Decided<Saved>>; rejectPending(ref: Required<ObjectRef>): Promise<Decided<{}>>; delete(ref: ObjectRef): Promise<Decided<{}>>;}class Objects { func open(_ ref: ObjectRef, action: OpenAction = .view) async throws -> Decided<Opened> func openField(_ ref: ObjectRef, field: String) async throws -> Decided<OpenedField> func save(_ locator: Locator, content: ObjectContent, baseVersion: Int, subject: String? = nil) async throws -> SaveResult<SaveOutcome> func create(_ folder: Locator, content: ObjectContent, subject: String? = nil) async throws -> SaveResult<Saved> func acceptPending(_ ref: ObjectRef) async throws -> Decided<Saved> func rejectPending(_ ref: ObjectRef) async throws -> Decided<Void> func delete(_ ref: ObjectRef) async throws -> Decided<Void>}class Objects { suspend fun open(ref: ObjectRef, action: OpenAction = OpenAction.VIEW): Decided<Opened> suspend fun openField(ref: ObjectRef, field: String): Decided<OpenedField> suspend fun save(locator: Locator, content: ObjectContent, baseVersion: Int, subject: String? = null): SaveResult<SaveOutcome> suspend fun create(folder: Locator, content: ObjectContent, subject: String? = null): SaveResult<Saved> suspend fun acceptPending(ref: ObjectRef): Decided<Saved> suspend fun rejectPending(ref: ObjectRef): Decided<Unit> suspend fun delete(ref: ObjectRef): Decided<Unit>}Objects groups the seven methods above into the namespace client.objects.