Plaintext lifetime
Plaintext exists only in the object that open returns. Call close() to discard it.
What close() discards
objects.open and objects.openField return plaintext. A record returns fields. A file returns
bytes. The plaintext stays available while your application holds the returned object.
close() discards the plaintext and every key the open used. After close(), the SDK cannot
recover the fields, the bytes or any key for that open.
const opened = await allowed(await client.objects.open({ locator }));if (!opened) return;render(opened);opened.close(); // discards the plaintext and its keysguard let opened = try await allowed(client.objects.open(ObjectRef(locator: locator))) else { return }render(opened)opened.close() // discards the plaintext and its keysval opened = allowed(client.objects.open(ObjectRef(locator))) ?: returnrender(opened)opened.close() // discards the plaintext and its keysAfter close(), the plaintext remains only on the screen your application rendered. To show the
object again, call open again. Each call gets a new decision and a new access event.
Nothing returned can be stored and reopened
A value that open returns on allow is not a credential. You cannot store it and give it back
to the SDK later to get the record. The SDK returns two things:
- plaintext to render
- a version number to track what you rendered
The SDK never returns a token that stands in for the plaintext.
Saving takes plaintext, returns a version
objects.save and objects.create take plaintext content, as RecordContent or FileContent.
On success they return a version number. They never return ciphertext or a key. The SDK builds the
stored object. Your application never sees its format.
const result = await client.objects.save(locator, { kind: 'record', name: 'Visit note', fields }, { baseVersion });let result = try await client.objects.save(locator, content: .record(RecordContent(name: "Visit note", fields: fields)), baseVersion: baseVersion)val result = client.objects.save(locator, content = RecordContent(name = "Visit note", fields = fields), baseVersion = baseVersion)A save returns a Saved with its version, or a BaseMoved that asks you to choose. Both describe
the save. Neither contains the content. Save and handle conflicts covers the full
flow, including saves while the Seald Healthcare Cloud is unreachable.
Masked fields
An open can succeed and still withhold some fields. OpenedRecord.masked lists each withheld
field with its own reason and text, like a Denied.
interface OpenedRecord extends OpenedBase { 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>,) : OpenedBaseThe open itself is an allow decision. Each masked field is a separate deny decision. Show the
fields you have. Show each masked field’s reason. The person then knows why the field is empty.
Next
- Access decisions for
Decided,Allowedand the outcome a masked field carries. - Open records and files for
OpenAction,FurtherActionandrequest(). - Save and handle conflicts for
SaveOutcome,BaseMovedand drafts.