Quickstart
Open a record from a folder and render it. Every feature you build on the Client SDK has this
shape: a call, a Decided and a render.
Create the SDK and connect
connect unlocks the device key for one tenant and returns a Client, with no session open yet.
import { create } from 'seald-sdk';
const sealdhealthcare = await create({ kind: 'desktop', release: '1.4.0', adapters: { unlock, signIn } });const client = await sealdhealthcare.connect(tenantId); // unlocks the device keylet sealdhealthcare = try await SealdHealthcare.create(Config(kind: .desktop, release: "1.4.0", adapters: Adapters(unlock: unlock, signIn: signIn)))let client = try await sealdhealthcare.connect(tenantId) // unlocks the device keyval sealdhealthcare = SealdHealthcare.create(Config(kind = ClientKind.DESKTOP, release = "1.4.0", adapters = Adapters(unlock = unlock, signIn = signIn)))val client = sealdhealthcare.connect(tenantId) // unlocks the device keySign in
session.signIn() runs the identity provider in the system browser and proves the device key at
once.
await client.session.signIn(); // signs in with the identity provider and proves the device keytry await client.session.signIn() // signs in with the identity provider and proves the device keyclient.session.signIn() // signs in with the identity provider and proves the device keyList a folder
A listing opens the folder index. It gets one decision, like any other open.
const listing = await client.folders.list(folder); // opens the folder index: one decisionif (listing.outcome !== 'allow') return show(listing);let folderResult = try await client.folders.list(folder) // opens the folder index: one decisionguard case .allow(let listing, _) = folderResult else { return show(folderResult) }val folderResult = client.folders.list(folder) // opens the folder index: one decisionif (folderResult !is Decided.Allow) return show(folderResult)val listing = folderResult.valueOpen a record
Each objects.open call gets one decision and records one access event. The decision is allow,
challenge or deny. Handle every case.
const opened = await client.objects.open({ locator: listing.entries[0].locator });switch (opened.outcome) { case 'allow': render(opened); // shows the fields and marks masked ones opened.close(); // discards the plaintext and its keys break; case 'challenge': return show(await opened.stepUp()); // signs in again, then repeats the request case 'deny': return showReason(opened.reason, opened.text); // shows why, and who can give access}let opened = try await client.objects.open(ObjectRef(locator: listing.entries[0].locator))switch opened {case .allow(let value, _): render(value) // shows the fields and marks masked ones value.close() // discards the plaintext and its keyscase .challenge(let challenge): return show(try await challenge.stepUp()) // signs in again, then repeats the requestcase .deny(let denied): return showReason(denied.reason, denied.text) // shows why, and who can give access}val opened = client.objects.open(ObjectRef(listing.entries[0].locator))when (opened) { is Decided.Allow -> { render(opened.value) // shows the fields and marks masked ones opened.value.close() // discards the plaintext and its keys } is Decided.Challenge -> return show(opened.stepUp()) // signs in again, then repeats the request is Decided.Deny -> return showReason(opened.reason, opened.text) // shows why, and who can give access}Every other feature has the same shape:
- Copy and Print from the surface call
opened.request('copy'). Each gets its own decision. - Saving calls
objects.save(locator, content, { baseVersion }). - Sharing, legal holds and evidence export each return a
Decidedto render.
Next
- Access decisions for
Decided,Allowed,Denied,Challengedand theallowedhelper this switch statement spells out by hand. - Adapters for
unlockandsignIn. - Open records and files for every option on
objects.open.