Skip to content

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 keys

After 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 });

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 }[];
}

The 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