Classes
PagesDifferError
Refused while the pages differ from the log: bonding, handing over the holder's wellknown.id, signing in for another device.
Extends
Error
Constructors
Constructor
new PagesDifferError(message?): PagesDifferError;
Parameters
| Parameter | Type |
|---|---|
message? | string |
Returns
Inherited from
Error.constructor
Constructor
new PagesDifferError(message?, options?): PagesDifferError;
Parameters
| Parameter | Type |
|---|---|
message? | string |
options? | ErrorOptions |
Returns
Inherited from
Error.constructor
Properties
Interfaces
CredentialRegistry
Where the platform lets sites find this wallet's credentials (the Digital Credentials API: Android's Credential Manager). None in a browser.
Methods
register()
register(credentials): Promise<string[]>;
Registers these presentable credentials (a batch as one, under its batch id) in place of what was there. Resolves the ids registered.
Parameters
| Parameter | Type |
|---|---|
credentials | SdJwtVcCredential[] |
Returns
Promise<string[]>
supported()
supported(): boolean;
Returns
boolean
HolderStore
Where the device keeps its HolderState: a file on a phone, localStorage in a browser.
Methods
load()
load(): Promise<HolderState | undefined>;
Returns
Promise<HolderState | undefined>
save()
save(state): Promise<void>;
Parameters
| Parameter | Type |
|---|---|
state | HolderState | undefined |
Returns
Promise<void>
Passkeys
The holder's wellknown.id passkeys (prd.md §4.7, §4.10): the system's prompts, through the platform.
Methods
create()
create(user, exclude): Promise<{
credentialId: string;
prfEnabled: boolean;
unlock?: Uint8Array<ArrayBufferLike>;
}>;
Makes a passkey for a keyring: exclude, the credential IDs it mustn't duplicate (E_EXCLUDED). Resolves its
credential ID, whether it does PRF, and the unlock secret if the provider computed it at registration.
Parameters
| Parameter | Type |
|---|---|
user | PasskeyUser |
exclude | string[] |
Returns
Promise<{
credentialId: string;
prfEnabled: boolean;
unlock?: Uint8Array<ArrayBufferLike>;
}>
tell()
tell(k): Promise<void>;
Tells the providers (the WebAuthn Signal API, where there is one) which passkeys open the keyring. Never throws.
Parameters
| Parameter | Type |
|---|---|
k | Keyring |
Returns
Promise<void>
unlock()
unlock(elsewhere?, credentialId?): Promise<{
credentialId: string;
secret: Uint8Array;
user?: string;
}>;
The passkey's unlock secret (its PRF output), its credential ID (base64url) and its user handle where the
system gives it, after the system's prompt. Any wellknown.id passkey, or credentialId's only; elsewhere
lets the system offer one from another device (a QR code). Rejects with code E_CANCELLED, E_NO_PASSKEY or E_NO_PRF.
Parameters
| Parameter | Type |
|---|---|
elsewhere? | boolean |
credentialId? | string |
Returns
Promise<{
credentialId: string;
secret: Uint8Array;
user?: string;
}>
QuietSealer
Seals a persona's records keys and the list of personas with a key bound to this device, without a prompt (prd.md §4.10): the Keystore on Android, a Secure Enclave key on iOS. None in a browser, where they're never kept: they come from the seed, which opens there without a prompt.
Methods
open()
open(sealed): Promise<Uint8Array<ArrayBufferLike>>;
Parameters
| Parameter | Type |
|---|---|
sealed | Uint8Array |
Returns
Promise<Uint8Array<ArrayBufferLike>>
seal()
seal(data): Promise<Uint8Array<ArrayBufferLike>>;
Parameters
| Parameter | Type |
|---|---|
data | Uint8Array |
Returns
Promise<Uint8Array<ArrayBufferLike>>
Type Aliases
AfterRecovery
type AfterRecovery = object;
Back in through custodians (prd.md §7.11, after a recovery): the dealing whose shares travelled, its policy, and its custodians by contact, each with whether this device can reach them yet. Until it deals again, those shares still open the keyring as it was; it deals again by itself once it reaches every one (upkeep).
Properties
Asked
type Asked = object[];
What a site asked for, as the screens show it before the holder decides (wallet.ts prepareAnswer).
Type Declaration
| Name | Type |
|---|---|
credential | object |
credential.subtitle | string |
credential.title | string |
paths | string[][] |
witness? | string |
Bequest
type Bequest = object;
What a beneficiary's device shows of a legacy: only once told, or once received.
Properties
| Property | Type |
|---|---|
error? | string |
from | object |
from.contact? | string |
from.name | string |
note? | string |
received? | string |
secrets? | string[] |
series | string |
told | boolean |
Bringing
type Bringing = object;
A passkey the holder brought in that opens a second keyring (findWithPasskey): what merging does, and doing it.
Properties
Methods
apply()
apply(): Promise<void>;
Returns
Promise<void>
cancel()
cancel(): void;
Returns
void
CheckSetup
type CheckSetup = object;
What the release watch checks (service/pages.ts): the release keys pinned (the key that signs now, then its successor) and the origins checked (by the manifest's names, with where to fetch each).
Properties
CodeOutcome
type CodeOutcome =
| {
id: string;
kind: "added" | "restored" | "here";
name: string;
}
| {
code: string;
here: string;
id: string;
kind: "conflict";
};
What a recovery code entered here did, once the holder is reached.
Contact
type Contact = Omit<ContactView, "devices"> & object;
A contact, as the screens show it. waiting: chosen here, not in the keyring yet.
Type Declaration
| Name | Type |
|---|---|
devices | ContactDeviceHere[] |
waiting? | boolean |
ContactDeviceHere
type ContactDeviceHere = ContactView["devices"][number] & object;
A contact's device, as the screens show it: with this device's bond with it, if there is one.
Type Declaration
| Name | Type |
|---|---|
bondId? | string |
ContactList
type ContactList = object;
The holder's contacts, and the bonds with someone else's devices that belong to none yet.
Properties
| Property | Type |
|---|---|
contacts | Contact[] |
unsorted | Bond[] |
CustodyPublic
type CustodyPublic = Pick<CustodyNote, | "epoch" | "threshold" | "count" | "waitMs" | "dealt" | "by" | "replicas" | "contacts"> & object;
The dealing to custodians, less its secrets (prd.md §7.11): what's read without the gate.
Type Declaration
| Name | Type |
|---|---|
custodians | number |
DealingView
type DealingView = object;
A dealing as the dealer sees it: each custodian by contact.
Properties
| Property | Type |
|---|---|
byThisDevice | boolean |
count | number |
custodians | object[] |
dealt | string |
epoch | string |
replicas | boolean |
threshold | number |
waitMs | number |
GateStatus
type GateStatus = "ready" | "no-lock" | "unavailable" | "browser";
Whether secrets can be gated here: 'ready' (a phone with a lock), 'no-lock', 'unavailable', or 'browser' (sealed, no prompt).
GiveAsk
type GiveAsk = object;
A browser's hand-over code, connected: the six digits, and the holder's answer.
Properties
Methods
cancel()
cancel(): void;
Returns
void
give()
give(): Promise<void>;
Returns
Promise<void>
GroupSignAsk
type GroupSignAsk = object;
What a member is asked to agree to, as their screen shows it before they decide.
Properties
| Property | Type |
|---|---|
actor? | string |
change? | object |
change.added | number |
change.members | number |
change.removed | number |
change.threshold | number |
group | string |
label | string |
scope? | string[] |
site? | string |
until? | number |
HeldLegacy
type HeldLegacy = object;
A legacy share held here for someone, as its custodian sees it: whose (their contact), the terms, and where it stands.
quiet: they've been active within the period (nothing to do). may-agree: the period has passed. agreed: this
custodian agreed, and waits for enough others. window: enough agree; the release goes at ends unless they show
a sign of life. released. unreadable: what's needed couldn't be read just now, so nothing moves.
Properties
HeldShare
type HeldShare = object;
A custodian's view of a share held for someone: whose, by contact (prd.md §7.12).
Properties
HolderAsk
type HolderAsk =
| {
asked: Asked;
bond: Bond;
request: Extract<BondRequest, {
kind: "openid4vp";
}>;
type: "proof";
approve: Promise<void>;
decline: void;
}
| {
bond: Bond;
request: Extract<BondRequest, {
kind: "return";
}>;
type: "return";
approve: Promise<void>;
decline: void;
}
| {
bond: Bond;
site: string;
type: "grant-key";
approve: Promise<void>;
decline: void;
}
| {
bond: Bond;
by?: string;
count: number;
name: string;
threshold: number;
type: "group-invite";
approve: Promise<void>;
decline: void;
}
| {
bond: Bond;
by?: string;
group: string;
label: string;
site: string;
type: "group-site-key";
approve: Promise<void>;
decline: void;
}
| {
asked: GroupSignAsk;
bond: Bond;
by?: string;
type: "group-sign";
approve: Promise<void>;
decline: void;
};
A bonded device's request that only the holder can answer, put to them by the app's screens. Each is answered
once: approve (which may ask the gate, and rejects, E_CANCELLED and the like, leaving it still asked) or decline.
Union Members
Type Literal
{
asked: Asked;
bond: Bond;
request: Extract<BondRequest, {
kind: "openid4vp";
}>;
type: "proof";
approve: Promise<void>;
decline: void;
}
Type Literal
{
bond: Bond;
request: Extract<BondRequest, {
kind: "return";
}>;
type: "return";
approve: Promise<void>;
decline: void;
}
Type Literal
{
bond: Bond;
site: string;
type: "grant-key";
approve: Promise<void>;
decline: void;
}
A contact asks for this holder's key at a site, to let them act for the contact there (prd.md §7.13).
Type Literal
{
bond: Bond;
by?: string;
count: number;
name: string;
threshold: number;
type: "group-invite";
approve: Promise<void>;
decline: void;
}
A contact (by, as the holder knows them) invites this holder into a shared identity (prd.md §7.14): its name, and how many of how many must agree.
Type Literal
{
bond: Bond;
by?: string;
group: string;
label: string;
site: string;
type: "group-site-key";
approve: Promise<void>;
decline: void;
}
A member of a shared identity asks for this holder's key at a site, for the group: it says who they are there to the other members.
Type Literal
{
asked: GroupSignAsk;
bond: Bond;
by?: string;
type: "group-sign";
approve: Promise<void>;
decline: void;
}
A member asks this holder to agree: a grant for the group at a site, or a change of its members.
HolderState
type HolderState = object;
What a device keeps of the holder's wellknown.id: the default persona's seed, sealed by this device's gate; this device's own merged keyring (prd.md §4.10), sealed under a key from that seed, so it opens only once the gate has opened the seed; and, on a phone, each persona's records keys and the list of personas, sealed by a hardware key without a prompt (never in the clear). Private to the device.
Properties
| Property | Type | Description |
|---|---|---|
codesChecked? | number | When the recovery-code copies were last checked against the keyring here (ms; keyring-holder.ts checkCodes). |
credentialId? | string | The passkey that reached the seed, where one did; with until, the end of its session where the app keeps the seed only for a while (the sign-in pages' unlock session, keyring-holder.ts sessionMs). |
custodyQuiet? | string | On a phone: the dealing's quiet part (service/holder.ts CustodyQuiet), sealed by the quiet sealer, so notices are read without the gate. |
how | "passkey" | "recovery-code" | "new" | "bond" | "custodians" | "browser" | - |
keyring? | string | The keyring as this device last had it (base64: keyring.ts sealKeyringHere under the seed). |
later? | string[] | - |
laterKey? | string | On a phone: the public key what bonded devices send about personas while the gate is closed is sealed to (persona-bonds.ts laterKeys, from the default's seed; base64), and what's waiting, sealed (sealForLater), merged the next time the gate opens the seed. |
legacyNotices? | LegacyNotice[] | - |
legacyQuiet? | string | On a phone: the legacy dealings' quiet parts (service/holder.ts LegacyQuiet), sealed by the quiet sealer. |
legacySeq? | Record<string, number> | Each legacy notice box, as far as this device has read it (by series), and what custodians said there. |
lifeAt? | number | When this device last wrote a sign of life (prd.md §7.11, legacy; ms). |
mailboxes? | object[] | On a phone: each held persona's records keys (seed.ts recordsKeys), the default's first, sealed by the quiet sealer (base64), with the persona's id. Absent in a browser, where they come from the seeds. |
notices? | RecoveryNotice[] | - |
noticeSeq? | number | The notice box, as far as this device has read it (the item sequence), and the recoveries it has heard of. |
recoveredBy? | string | The recovery this device got back in by (its id): its notices are this device's own, not one to stop. |
redeal? | string | Back in through custodians (prd.md §7.11): the dealing whose shares travelled, until one is dealt again (here or on another of the holder's devices). Until then those shares still open the keyring as it was. |
sealedSeed | string | browser: a seed made in a browser that can't do passkeys with PRF, kept there (the sign-in pages). |
several? | boolean | Whether the holder has more than one persona in use: all a sign-in page knows of them before the keyring opens. |
since | string | - |
summary? | string | On a phone: the list of personas (PersonaList: names, states, fingerprints, no seeds or keys), sealed the same way. |
told? | string | What the passkey providers were last told (passkeys.ts signalled), so they're told again only when it changes. |
until? | number | - |
vaultKeys? | string | The vault keys (prd.md §7.11; custodians.ts): the recovery key and the secrets key, with the dealing's epoch, sealed under the default persona's seed as keyring is (never in the keyring, which a passkey opens). Only on the holder's own devices, brought by their bonds. |
writer? | string | This device's writer id for keyring edits (keyring.ts newWriter). |
Joining
type Joining = object;
The side that joins, once connected: the six digits to compare, what the other side said, and the holder's answer.
Bonding as someone else's, confirm takes the contact the other device belongs to (prd.md §7.12).
Properties
Methods
cancel()
cancel(): void;
Returns
void
confirm()
confirm(contact?): Promise<Bond>;
Parameters
| Parameter | Type |
|---|---|
contact? | ContactPick |
Returns
Promise<Bond>
LegacyNotice
type LegacyNotice = object;
A legacy custodian's agreement to a release, as the holder's notice box told this device (prd.md §7.11).
Properties
LegacyPublic
type LegacyPublic = Pick<LegacyNote, | "series" | "epoch" | "threshold" | "count" | "quietMs" | "windowMs" | "dealt" | "by" | "contacts" | "told" | "replicas">;
A legacy dealing, less its secrets (prd.md §7.11): what's read without the gate, by the beneficiary's contact.
LegacyView
type LegacyView = object;
A legacy dealing, as the holder's devices show it: for whom, to whom, on what terms, and what's left to them.
Properties
OfferAsk
type OfferAsk = object;
An offer held here, put to the holder: keep it (behind the gate) or decline.
Properties
| Property | Type | Description |
|---|---|---|
bond | Bond | - |
contact? | string | From someone else's device (a copy given, prd.md §7.14): their name as this holder knows them, where they're a contact. |
offer | Offer | - |
Methods
decline()
decline(reason): void;
Parameters
| Parameter | Type |
|---|---|
reason | string |
Returns
void
keep()
keep(): Promise<void>;
Keeps it here (the gate asks now, to seal it) and says so to the device that offered it. Rejects (E_CANCELLED…) and stays asked if it can't.
Returns
Promise<void>
PagesCheck
type PagesCheck = object;
Where the release watch stands, for the screens.
Properties
| Property | Type | Description |
|---|---|---|
checking | boolean | A check is running. |
origins | string[] | The origins it checks. |
standing? | Standing | - |
status | "off" | "never" | "ok" | "differs" | off: nothing to check here; never: no check has got an answer yet. |
test? | boolean | Pointed at a test stack (a development build). |
unchecked? | object | The latest try got no answer: when, and why. |
unchecked.at | number | - |
unchecked.reason | string | - |
web | boolean | Where this wallet runs, for what the screens say about the check's limits. |
PasskeyUser
type PasskeyUser = object;
The WebAuthn user entity of a passkey made for a keyring (passkeys.ts passkeyUser): its ring as the handle, base64url.
Properties
PersonaList
type PersonaList = object;
The personas as the screens show them, the passkeys that open the keyring, whether their names carry the default's name, the dealing, and the contacts (prd.md §7.12).
Properties
| Property | Type |
|---|---|
contacts? | ContactView[] |
custody? | CustodyPublic |
grants? | GrantView[] |
groups? | GroupView[] |
legacy? | Record<string, LegacyPublic> |
names? | boolean |
passkeys | object[] |
personas | PersonaView[] |
tombs? | ContactTombs |
Recognising
type Recognising = object;
A recovery a custodian is taking part in, before confirming: the code to compare.
Properties
Methods
cancel()
cancel(): void;
Returns
void
confirm()
confirm(): Promise<void>;
Returns
Promise<void>
Recovery
type Recovery = object;
A recovery begun on this device: the link to give custodians, the code, and how far it has got.
Properties
| Property | Type |
|---|---|
code | string |
done? | boolean |
error? | string |
id | string |
shares | number |
since | string |
threshold? | number |
url | string |
RecoveryNotice
type RecoveryNotice = object;
A recovery under way, as a custodian's notice told this device (prd.md §7.11), and whether the holder stopped it.
Properties
ReleasePorts
type ReleasePorts = object;
What the release watch needs from the platform: what to check, a fetch, and somewhere to keep its state.
Properties
Methods
load()
load(): Promise<unknown>;
What the watch keeps between checks, on this device only.
Returns
Promise<unknown>
save()
save(state): Promise<void>;
Parameters
| Parameter | Type |
|---|---|
state | unknown |
Returns
Promise<void>
setup()
setup(): CheckSetup | undefined;
What this device checks; undefined: nothing here.
Returns
CheckSetup | undefined
Say
type Say = (key, values?) => string;
Puts one of the service's words (SayKey) in the holder's language, with its values filled in.
Parameters
| Parameter | Type |
|---|---|
key | SayKey |
values? | Record<string, string | number> |
Returns
string
SayKey
type SayKey = | "reason.keep" | "reason.default" | "reason.records" | "reason.personas" | "reason.recoveryCode" | "reason.give" | "reason.signIn" | "reason.bond" | "reason.givePersonas" | "reason.deal" | "reason.keepShare" | "reason.stop" | "reason.recoverable" | "reason.contacts" | "reason.keepLegacyShare" | "reason.legacy" | "reason.releaseLegacy" | "error.notBeneficiary" | "error.shortQuiet" | "error.noHolder" | "error.badRecoveryCode" | "error.notReached" | "error.noPersona" | "error.badRecoveryLink" | "error.noRequest" | "error.notCustodians" | "error.shortWait" | "error.noContact" | "pages.refused" | "custody.noScreenLock" | "custody.notShared" | "reason.grant" | "reason.grantBack" | "reason.grantDrop" | "reason.grantKeep" | "reason.grantForget" | "reason.grantKey" | "grants.noConfig" | "grants.notAccepted" | "grants.noContact" | "grants.unknownScope" | "grants.tooLong" | "grants.noDevice" | "grants.noAnswer" | "grants.unknown" | "grants.notAContact" | "grants.notForMe" | "shares.noContact" | "shares.noSecret" | "shares.noDevice" | "reason.groupFound" | "reason.groupJoin" | "reason.groupNews" | "reason.groupSite" | "reason.groupAgree" | "reason.groupGrant" | "reason.groupChange" | "groups.unknown" | "groups.noDevice" | "groups.noAnswer" | "groups.noName" | "groups.badThreshold" | "groups.notEnough" | "groups.notSigned" | "groups.notAContact" | "groups.notAgreed" | "groups.notFounded" | "groups.notMember";
The words the service puts in front of the holder: the gate's prompts, and errors. In the holder's language.
Secret
type Secret = object;
A secret as the holder enters it: its name, kind and value, and where it's for.
Properties
| Property | Type |
|---|---|
copyOf? | string |
fileName? | string |
name | string |
secretType | SecretCredential["secretType"] |
service? | string |
value | Uint8Array |
ServiceEvent
type ServiceEvent = | "log" | "bonds" | "offers" | "pages" | "holder" | "records" | "custody" | "contacts" | "legacy" | "grants" | "groups";
What changed, for screens to read again: the log (and so the secrets catalogue), bonds, offers held, the release watch, the holder's state here, the personas' records (this device's consents filed in them), the custodians (shares offered, held or released, a dealing, a recovery under way, prd.md §7.11), the contacts (§7.12).
ServicePorts
type ServicePorts = object;
Everything the service needs from the platform, and nothing else: an app supplies these adapters (a browser's, a phone's, an in-memory set for tests) and the service does the rest.
Properties
| Property | Type | Description |
|---|---|---|
bonds | BondStore & LogStore & OfferStore | Bonds (with update), the sync log, offers held. |
clock? | Clock | The time; tests move it. |
credentials | CredentialStore | Documents, secrets' notes, consents. |
custodyLimits? | () => object | The wait a dealing may be made with, at least (prd.md §7.11: 72 hours); a development build's tests shorten it. |
device | Device | What this device calls itself, and its platform. |
drops | DropStore | Drop boxes at the relay: what bonded devices leave for this one while it's away. |
fetch? | typeof fetch | Fetch, for sites' privacy declarations and witnesses' discovery. |
gate | Sealer | The biometric gate (a browser: a non-extractable key, no prompt). Seals secrets and the holder's seed. |
holderState | HolderStore | The holder's state on this device (the default persona's sealed seed, this device's keyring copy). |
keys | KeyStore | The device's identity key and credential keys. |
passkeys | Passkeys | The platform's passkeys, with PRF: the holder's unlock. |
push? | object | This device's push token as last fetched, straight away (for answering pings). |
push.known | PushHandle | undefined | - |
quiet? | QuietSealer | On a phone: what's read without the gate. None in a browser. |
registry? | CredentialRegistry | Where sites find this wallet's credentials (Android's Credential Manager); none in a browser. |
relay | Relay | The relay's mailboxes. |
release? | ReleasePorts | The release watch: kivi's check of the pages wellknown.id serves against the signed release log. |
say | Say | The service's words, in the holder's language. |
store | EncryptedStore | The encrypted store (keyrings, recovery-code copies, the personas' mailboxes) and drop boxes, at the relay. |
trust? | TrustStore | Document signers' trust anchors (CSCA certificates), for checking passports and ID cards. |
Methods
gateStatus()
gateStatus(): Promise<GateStatus>;
Whether secrets can be gated here, and how.
Returns
Promise<GateStatus>
wake()
wake(bond): Promise<boolean>;
Asks the relay to wake a bonded phone (a content-free push). False if it can't.
Parameters
| Parameter | Type |
|---|---|
bond | Bond |
Returns
Promise<boolean>
ShareAsk
type ShareAsk = object;
A share offered to this device, put to its holder. contact: whose, as this holder knows them (none yet: accepting
takes a name, and makes them a contact). copy: sent by another of this holder's own devices, which kept it there.
devices: this holder's other devices it could be kept on too. Accept (with a name, if there's no contact; and
the other devices chosen), or decline.
Properties
Methods
accept()
accept(o?): Promise<void>;
Parameters
| Parameter | Type |
|---|---|
o? | { keepOn?: readonly string[]; name?: string; } |
o.keepOn? | readonly string[] |
o.name? | string |
Returns
Promise<void>
decline()
decline(reason): void;
Parameters
| Parameter | Type |
|---|---|
reason | string |
Returns
void
SignInAsk
type SignInAsk = object;
A sign-in page's request, connected: the site, which persona would sign (the chooser), and the holder's answer.
Properties
Methods
decline()
decline(reason?): void;
Parameters
| Parameter | Type |
|---|---|
reason? | string |
Returns
void
sign()
sign(persona?, grant?): Promise<void>;
Signs as persona (the chooser's, if none is named), behind the gate, and sends only the self-issued token;
then files the sign-in in that persona's mailbox. With grant (one of acting's ids), acts for that contact:
the persona the grant names signs, and the grant goes with the token. Rejects E_CANCELLED (still asking) if the
holder closes the prompt.
Parameters
| Parameter | Type |
|---|---|
persona? | string |
grant? | string |
Returns
Promise<void>
SiteTerms
type SiteTerms = Delegation & object;
What a site says about delegation, as the screens show it before a grant is made.
Type Declaration
| Name | Type |
|---|---|
site | string |
Standing
type Standing = object;
The result of the latest check that got an answer: the pages served as the signed release lists them, or not.
Properties
| Property | Type |
|---|---|
at | number |
checked | number |
commit? | string |
differences? | Difference[] |
release? | number |
rollingOut? | string[] |
scope | Scope |
status | "ok" | "differs" |
WalletService
type WalletService = ReturnType<typeof createWalletService>;
The wallet service: its commands, grouped by what they're about (holder, bonds, contacts, custodians…).
Variables
CHECK_STANDS_MS
const CHECK_STANDS_MS: number;
How long a check's result stands before the next bonding or sign-in checks again.
DAILY_MS
const DAILY_MS: number;
How often the app checks while open, and checks fonts and images too.
Functions
createWalletService()
function createWalletService(ports): object;
Makes the wallet service from the platform's ports: once per app, as a second one over the same storage would answer the same bonds twice. Two services over the same storage behave like the same device restarted.
Parameters
| Parameter | Type |
|---|---|
ports | ServicePorts |
Returns
| Name | Type | Default value | Description |
|---|---|---|---|
bonds | object | - | - |
bonds.deviceNames() | () => Promise<Map<string, string>> | sync.deviceNames | The devices this one knows by name, by did:key: those its bonds name, and those the logs held here describe. Who signed a record (records.ts whoSigned) is named from it. |
bonds.gaps() | () => Promise<Gap[]> | sync.gaps | - |
bonds.give() | (bond, ids) => Promise<void> | - | Gives a limited bond's device personas; takes them back (a request to forget). |
bonds.list() | () => Promise<Bond[]> | - | - |
bonds.personasToGive() | () => Promise<PersonaView[]> | holder.personasToGive | The personas this device could give a limited device. The personas this device could give a limited device: those in use, by name. |
bonds.reachable() | (bond, timeoutMs?) => Promise<boolean> | - | Whether bond's device is there to answer now (its answer brings its current push token, kept on the bond). |
bonds.remove() | (bond) => Promise<void> | sync.removeDevice | Removes a bonded device: one of the holder's own leaves all their devices; anyone else's, just this one. |
bonds.takeBack() | (bond, ids) => Promise<void> | - | - |
bonds.untilReachable() | (bond, timeoutMs?, cancelled?) => Promise<boolean> | - | Waits for bond's device to be there, pinging every couple of seconds; stops early if cancelled(). |
bonds.wake() | (bond) => Promise<boolean> | - | Asks the relay to wake bond's device (with its push token as last heard). False if it can't. |
join() | (url) => Promise<Joining> | - | The side that joins: from a scanned code (or its link), connects, and says what the other side asks. Refused while the pages differ. |
pair() | ( kind, given?, origin?, contact? ) => Promise<Pairing> | - | The side that starts: the QR code to show (and its link), then the six digits, then the bond. kind: what the other device will be; given: the personas a limited device is given; contact: someone else's device's contact, chosen before the code is shown (prd.md §7.12). Refused while wellknown.id's served pages differ from its release log. origin: the web app that opens the link on a device without the app. |
reach() | (bond, o?) => Promise<void> | - | Makes sure the app is open on bond's device before asking it anything. If it isn't (notThere), wakes it (a notification that only says a request is waiting) where it can be (woken: whether it could), and waits up to the notification's two minutes for the holder to open it. Rejects if it never comes. |
close() | () => void | - | The app has gone to the background. |
contacts | object | - | Contacts (prd.md §7.12): the people the holder knows, each a name only the holder's devices see, over the bonds with their devices. Chosen at bonding (bonds.pair, Joining.confirm); choose gives one to a bond that has none. |
contacts.choose() | (bond, pick) => Promise<string> | contacts.choose | Which contact bond's device is (prd.md §7.12): one the holder has, or a new one by the name they typed (never the device's). Kept on the bond now, and taken into the keyring as soon as it can be. |
contacts.list() | () => Promise<ContactList> | contacts.list | The holder's contacts, without asking (see above). |
contacts.merge() | (from, into) => Promise<void> | contacts.merge | - |
contacts.move() | (did, into) => Promise<void> | contacts.move | - |
contacts.remove() | (id, opts) => Promise<void> | contacts.remove | Removes a contact: what they told forgotten, the bonds made from contacts with their devices ended; with bonds (the default), the bonds with their devices made by a ceremony too, on each of the holder's devices. |
contacts.rename() | (id, name) => Promise<void> | contacts.rename | - |
contacts.tell() | (id, on) => Promise<void> | contacts.tell | The holder's answer to "tell them about my other devices?" (asked once per contact). Yes sends them now; no after a yes asks their devices to forget what they were told, and ends the bonds made from it (settle). |
custodians | object | - | Custodians (prd.md §7.11): dealing shares of a recovery key to people the holder chooses, holding theirs, and getting back in through them. |
custodians.afterRecovery() | () => Promise<AfterRecovery | undefined> | custodians.afterRecovery | Back in through custodians, and not dealt again yet: the dealing to retire, and whom this device reaches. |
custodians.callOff() | (shareId) => Promise<void> | custodians.callOff | A recovery under way through this custodian, called off here (before its release). |
custodians.cancelRecovery() | () => Promise<void> | custodians.cancelRecovery | - |
custodians.checkNotices() | () => Promise<boolean> | custodians.checkNotices | Reads the notice box (from where this device left off) and the veto box: recoveries under way, and stops. |
custodians.confirmHeld() | () => Promise<void> | custodians.confirmHeld | - |
custodians.deal() | (o) => Promise<DealingView> | custodians.deal | Deals to custodians (prd.md §7.11): contactIds the people (§7.12), each bonded here through at least one of their devices, any threshold of whom get the holder back in, after waitMs. A dealing already made is ended first (dealt again: a new key, a new epoch; its vault removed, custodians left out told to drop their shares). The gate asks once. |
custodians.dealing() | () => Promise<DealingView | undefined> | custodians.view | The current dealing, as the dealer sees it: each custodian's answer and last confirmation (stale after 60 days). |
custodians.dealWithout() | (id) => Promise<DealingView> | custodians.dealWithout | Deals again without contact id (prd.md §7.12: removing a contact who is a custodian): the same policy to the others, the threshold no more than are left. Throws if fewer than MIN_THRESHOLD would be left. The dealing before is ended as any dealing again ends it: the one left out told to drop their share. |
custodians.dropHeld() | (id) => Promise<void> | custodians.dropHeld | A share this custodian wants to delete: told to the holder (as no longer held) the next time they ask. |
custodians.held() | () => Promise<HeldShare[]> | custodians.held | The shares this device holds for others (accepted), newest first. |
custodians.markRecoverable() | (secretId, on) => Promise<void> | custodians.markRecoverable | Marks a secret kept here recoverable (prd.md §7.11): its value goes into the secrets vault under the secrets key (made now if there's none yet; a dealing carries it in the vault). Or takes it out again. The gate asks. |
custodians.nextAsk() | () => Promise<ShareAsk | undefined> | custodians.nextAsk | The share waiting longest for this device's holder, if any, to put to them. |
custodians.notices() | () => Promise<RecoveryNotice & object[]> | custodians.notices | The recoveries this device has heard of, newest first, each custodian named as the holder knows them (prd.md §7.12). |
custodians.pollRecovery() | () => Promise<boolean> | custodians.pollRecovery | Reads the release box: each release that opens and verifies is kept, by index; with the threshold of one dealing, the key is rebuilt, the newest vault that opens found (the store's, the replicas'), the keyring and the vault keys kept, and the recoverable secrets brought back. Resolves true once the holder is reached. |
custodians.recognise() | (contactId, link) => Promise<Recognising> | custodians.recognise | The holder has lost everything and shows this custodian a recovery link (prd.md §7.11): whose it is, by contact (§7.12), picks the share held for them; the new device's key is read from the request box, and the code both screens show is returned to compare, in person or on a call. confirm posts the notice to the holder's devices and starts the wait; nothing is released before it ends. |
custodians.recovery() | (origin?) => Promise<Recovery | undefined> | custodians.recovery | The recovery begun here, if any, and how far it has got. |
custodians.releaseDue() | () => Promise<number> | custodians.releaseDue | For each recovery waiting here: the veto box read (a stop by the veto key withholds the share); past the wait, with the veto box read successfully just now, the share released to the new device's key alone, with a signed statement. The gate opens the share for that. Returns how many were released. |
custodians.startRecovery() | (origin?) => Promise<Recovery> | custodians.startRecovery | Begins getting back in through custodians (prd.md §7.11), on a device that hasn't reached the holder: a fresh key pair for the recovery, its public key in the request box, the link to give each custodian, and the code every screen will show. The release box is polled while the service is open. |
custodians.stop() | (recovery) => Promise<void> | custodians.stop | Stops a recovery (prd.md §7.11): a veto signed with the keyring's veto key (the gate asks), for every custodian to read. |
debug | object | - | For development tools: this device's latest asks, and what each listener is doing. |
debug.asked() | () => object[] | - | - |
debug.listening() | () => Map<string, { at: number; state: string; }> | - | - |
declared() | (origin) => Promise<Privacy | null> | - | What a site says it does with what it asks for: its config's privacy block (null: it publishes none). |
device | Device | ports.device | What this device calls itself (the device port). |
gateStatus() | () => Promise<GateStatus> | - | Whether secrets can be gated here (the gate port's status). |
give | object | - | - |
connect() | (url) => Promise<GiveAsk | undefined> | - | Connects to the browser showing url. Undefined if this device hasn't reached the holder. Refused while the pages differ. |
grants | object | - | - |
grants.drop() | (id) => Promise<void> | delegation.drop | Stops acting for a contact under a grant held here: ended in the keyring (the giver isn't asked anything). |
grants.give() | (o) => Promise<string> | delegation.give | Lets the contact act for this holder at site for days, doing what scopes (the site's names) say. Asks the contact's device for their key there first (their kivi asks them, up to waitMs). Resolves the grant's id. |
grants.list() | () => Promise<GrantView[]> | delegation.list | The grants as the keyring has them (without asking: from the list the holder already sees). |
grants.takeBack() | (id) => Promise<void> | delegation.takeBack | Takes a grant back: gone from its mailbox at once, ended in the keyring, and the contact's devices asked to forget it. |
grants.terms() | (site) => Promise<SiteTerms> | delegation.terms | The site's terms for delegation, from its wellknown.id config. Throws if it has none, or doesn't accept it. |
groups | object | - | Shared identities (prd.md §7.14): founded with contacts, acting at a site through a grant to one member that k members sign, members changed by k of them. Built, and not offered until delegation's legal review (the app decides). |
groups.act() | (o) => Promise<string> | groups.act | Asks to act for the group at site for days, doing what scopes (the site's names) say: the members' keys there, then their agreement, until k agree (each member's kivi asks them, up to waitMs). Resolves the grant's id. |
groups.changeMembers() | (o) => Promise<void> | groups.changeMembers | Changes the group: remove (members' keys), add (contacts, invited first), threshold. Signed by k members of the statement before (each asked). Resolves when it's agreed and the members are told. |
groups.found() | (o) => Promise<string> | groups.found | Founds a shared identity with contactIds, threshold of all its members (the holder too) to agree. Each contact's kivi asks them; those who say yes are its founding members (it needs two members and threshold). Resolves its id here. |
groups.leave() | (group) => Promise<undefined> | groups.leave | - |
groups.list() | () => Promise<GroupView[]> | groups.list | The groups as the screens show them (without asking: from the list the holder already sees). |
groups.rename() | (group, label) => Promise<undefined> | groups.rename | - |
groups.takeBack() | (group, id) => Promise<void> | groups.takeBack | Takes one of the group's grants back (any member may): gone from its mailbox at once, ended, the members told. |
holder | object | - | - |
holder.addPasskeyHere() | () => Promise<void> | holder.addPasskeyHere | Adds a passkey to the holder's keyring, deliberately (another provider, say): made with the keyring's user handle and names, and excludeCredentials listing its passkeys, so a provider that already keeps one refuses (E_EXCLUDED). Its PRF output files a copy of the keyring. |
holder.addPersona() | (name) => Promise<string> | holder.addPersona | Adds a persona named name (made unique). Resolves its id. |
holder.addPersonaWithCode() | (code) => Promise<CodeOutcome> | holder.addPersonaWithCode | A recovery code entered once the holder is reached: its persona joins the keyring, in use. A forgotten persona comes back (its code is the deliberate act that may). One already here under another name is the rename conflict, settled by settleConflict. |
holder.defaultPersonaId() | () => Promise<string | undefined> | holder.defaultPersonaId | The default persona's id (its fingerprint, in full), which a home seal is drawn from (prd.md §4.10). Read without asking: on a phone from the quietly sealed list of personas, in a browser from the default's seed. Undefined while no persona is held here (or, on a phone, before that list has been sealed). |
holder.findWithPasskey() | (elsewhere) => Promise<Bringing | undefined> | holder.findWithPasskey | - |
holder.forget() | () => Promise<void> | holder.forget | Forgets the holder's wellknown.id on this device (their personas stay reachable through their unlocks). |
holder.forgetPersona() | (id) => Promise<undefined> | holder.forgetPersona | - |
holder.makeDefault() | (id) => Promise<undefined> | holder.makeDefault | - |
holder.makeRecoveryCode() | (id?) => Promise<{ code: string; name: string; short: string; }> | holder.makeRecoveryCode | A new recovery code for a persona (the default, if none is named), filed in the store (with its name), noted in the keyring and in every passkey's copy of it. Resolves what to show once: the code, the persona's name and fingerprint. |
holder.openRecords() | () => Promise<void> | holder.openRecords | On a phone whose personas aren't sealed for quiet reading yet: opens the seed once, through the gate, to seal them. |
holder.personaList() | () => Promise<PersonaList | undefined> | holder.personaList | The holder's personas, without asking (personaList, below). |
holder.personaSites() | () => Promise<Map<string, number>> | holder.personaSites | How many sites each persona has been used at, from its mailbox (sign-ins and consents): by persona id. |
holder.records() | () => Promise<MailboxEntry[]> | holder.records | Everything in the personas' mailboxes, each record with the device that signed it (verified): sign-ins from the holder's browsers (unsigned), consents and sign-ins from every wallet holding the persona. A record in two mailboxes (filed again after the default changed) is listed once. |
holder.recordsWaiting() | () => Promise<boolean> | holder.recordsWaiting | Whether the records and the personas wait for the gate (a phone where they aren't sealed for quiet reading yet). |
holder.removeRecoveryCode() | (id, copyId) => Promise<void> | holder.removeRecoveryCode | Removes one of a persona's recovery codes (prd.md §4.10): marked removed in the keyring (every passkey's copy hears it), then its copy deleted from the store, so the code opens nothing. Should the app stop between the two, the next device to check its codes deletes it. |
holder.rename() | (id, name) => Promise<void> | holder.rename | Renames a persona; every recovery-code copy of it the keyring knows is rewritten with the new name. |
holder.reuse() | (id) => Promise<undefined> | holder.reuse | - |
holder.setAside() | (id) => Promise<undefined> | holder.setAside | - |
holder.setNames() | (on) => Promise<undefined> | holder.setNames | - |
holder.settleConflict() | (keepThisName) => Promise<void> | holder.settleConflict | The rename conflict's answers: keep the name here (the code's copy rewritten with it), or rename back to the code's. |
holder.startNew() | () => Promise<void> | holder.startNew | For someone new to wellknown.id: makes their passkey, and their first persona with it. The unlock comes with the passkey when its provider computes PRF at registration, so they're asked once; else the passkey is asked for it. |
holder.state() | () => Promise<HolderState | undefined> | holder.state | What this device knows of the holder. What an older version kept that this one doesn't read (records keys in the clear; one persona's sealed records keys) is let go of at once (a clean break). |
holder.unlockWithPasskey() | (elsewhere) => Promise<void> | holder.unlockWithPasskey | With the holder's passkey (from this phone, or elsewhere through the system's QR code), finds their keyring. Rejects with code E_NO_HOLDER if the passkey opens none (they're new: see startNew). |
holder.unlockWithRecoveryCode() | (code) => Promise<void> | holder.unlockWithRecoveryCode | With a recovery code, on a device that hasn't reached the holder yet: the persona it's for, kept here as its own. |
legacy | object | - | Legacy (prd.md §7.11): chosen secrets left to a beneficiary, released by custodians on a long absence they agree on, after a veto window; never the identity. Built, and not offered until the legal review (the app decides whether to show it). |
legacy.agree() | (shareId) => Promise<void> | legacy.agree | This custodian agrees to a release (prd.md §7.11): only once the period of quiet has passed. Signed with its agreement key, left in the agreement box (the other custodians read it) and the holder's notice box (their devices hear of it, and any sign of life voids it). |
legacy.bequests() | () => Promise<Bequest[]> | legacy.bequests | What this device shows of legacies left to its holder: those the holder chose to tell them of, and those received. |
legacy.checkNotices() | () => Promise<boolean> | legacy.checkNotices | Reads each legacy's notice box from where this device left off: the custodians' agreements, by who they're left to. |
legacy.checkReleases() | () => Promise<number> | legacy.checkReleases | - |
legacy.deal() | (o) => Promise<LegacyView> | legacy.deal | Deals a legacy key for beneficiary (a contact) to custodians (contactIds, other contacts, each reached here), any threshold of whom may release it to the beneficiary alone, after quietMs without a sign of life and a veto window of windowMs. The beneficiary's devices are given the box secret quietly, and told they're named only if tell. Dealt again for the same beneficiary: a new key and epoch; the head before removed, its custodians told to drop their shares. The gate asks once. |
legacy.end() | (beneficiary) => Promise<void> | legacy.end | Ends the legacy for beneficiary: the keyring's note gone, the head removed, its custodians told to drop their shares, the beneficiary's devices told to forget the box secret (a compliant kivi does when it hears; it could have kept a copy, which opens nothing without the custodians). The secrets stay where they're kept. The gate asks. |
legacy.held() | () => Promise<HeldLegacy[]> | legacy.held | The legacy shares this device holds for others, each with where it stands (read now). |
legacy.imHere() | () => Promise<number> | legacy.imHere | - |
legacy.leave() | (secretId, beneficiary, on) => Promise<void> | legacy.leave | Leaves a secret kept here to beneficiary (prd.md §7.11), or takes it back: its value into their content (under the content key, made now if there's none yet), or out of it. The gate asks. |
legacy.list() | () => Promise<LegacyView[]> | legacy.views | The legacies the keyring notes, each with its terms and what's left to the beneficiary from here. |
legacy.notices() | () => Promise<LegacyNotice & object[]> | legacy.notices | The custodians' agreements this device has heard of, newest first, each with who it's left to, by name. |
legacy.releaseDue() | () => Promise<number> | legacy.releaseDue | For each legacy share this custodian agreed to release: past the veto window, with the life entry, the veto box and the agreement box read in this same run and still enough agreements since the latest sign of life, the share sealed to the release key alone, with a statement. The gate opens the share. Resolves how many were released. |
legacy.signOfLife() | (force) => Promise<number> | legacy.signOfLife | A sign of life (prd.md §7.11): written to each legacy's life entry at most daily (or now, force: "I'm here", also into the veto box), from any of the holder's devices that holds the keyring, without the gate. The dealing device also sends one over its bonds with the custodians, at most monthly. Resolves how many legacies it was written for. |
legacy.withoutContact() | (id, o) => Promise<{ dealtAgain: string[]; ended: string[]; tooFew: string[]; }> | legacy.withoutContact | Removing a contact (prd.md §7.12): a legacy left to them ends; one they hold a share of is dealt again without them (dealAgain), where enough custodians are left (else it stays as it is, their share with them until it's dealt again, and tooFew names it). Only the device that dealt it knows its custodians: elsewhere those are left alone. |
offers | object | - | - |
offers.askBack() | (bond, remoteId, name) => Promise<Uint8Array<ArrayBufferLike>> | offers.askBack | - |
offers.keepSecret() | (secret, where) => Promise<{ deliveries: Delivery[]; record: SecretCredential; }> | offers.keepSecret | Keeps a new secret: here first if the holder chose (so leaving part way loses nothing), then offered to each of devices at once (open: whether each answered the form's last check). Resolves once every offer is handed over, live or into a drop box, with the note of the secret and how each went; then it's in this device's log and on its way to the others. Nobody's answer is waited for. Throws if the secret ends up nowhere at all. |
offers.nextAsk() | () => Promise<OfferAsk | undefined> | offers.nextAsk | The offer waiting longest for the holder here, if any, to put to them. Where this device can't gate secrets (a phone without a screen lock), it's declined at once, and the next is looked at. |
on() | (event, fn) => () => void | - | - |
open() | (asks) => void | - | The app is open and in front (requests.ts): it listens for its bonded devices; asks puts to the holder what only they can answer. |
pages | object | - | - |
pages.check() | (o) => Promise<PagesCheck> | pages.check | Checks the served pages now, or (unless force) takes a result less than 10 minutes old. Resolves the check as it stands: a difference found earlier stands through a check that got no answer. |
pages.now() | () => PagesCheck | pages.now | - |
settled() | () => Promise<void> | - | Resolves once nothing this device began on opening (a refresh, an upkeep) is still under way: a test moving its clock waits for it. |
shares | object | - | Sharing with a contact (prd.md §7.14): a secret lent (it stays here; their devices ask, and the holder's asked each time) or given (a copy that's theirs; taking it back is a request to forget). Never a persona, records or documents. |
shares.give() | (secretId, contactId) => Promise<number> | shares.give | Gives a contact a copy of a secret kept here, as theirs: opened behind this device's gate, then offered to each of their devices to keep (their kivi asks them). Resolves how many devices it was handed to. |
shares.lend() | (secretId, contactId) => Promise<void> | shares.lend | Lends a secret kept here to a contact: listed for every device of theirs; they ask, and this holder's asked each time. |
shares.news() | () => ShareNews[] | shares.news | - |
shares.of() | (secretId) => Promise<{ given: object[]; lent: object[]; }> | shares.of | What's lent and given, by contact, for a secret kept here (its card). |
shares.present() | (o) => Promise<void> | shares.present | Shows a contact what a credential says, bound to them: they can check it, not use it as their own. Shows a contact what a credential says: only paths, key-bound to their device (its did:key) and a nonce it gave, so they can check it but not use it as their own. Needs their kivi open (it gives the nonce). Resolves once their kivi has checked it. |
shares.presentable() | () => Promise<object[]> | shares.presentable | What can be shown to a contact: each credential, by title, with the claims it can disclose one by one (their paths). |
shares.stopLending() | (secretId, contactId) => Promise<void> | shares.stopLending | Stops lending a secret to a contact: their devices are taken off its list, so nothing more reaches them. |
shares.takeBack() | (secretId, contactId) => Promise<void> | shares.takeBack | Takes back a copy given: each of the contact's devices is asked to forget it (a compliant kivi deletes it when it hears). They could have copied it first: the screens say so, and that a password given should be changed. |
signIn | object | - | - |
connect() | (url) => Promise<SignInAsk | undefined> | - | Connects to the page showing url. Undefined if this device hasn't reached the holder. Rejects (and tells the page why) while the pages differ. |
sync | object | - | - |
sync.otherDevices() | () => Promise<CatalogueDevice[]> | sync.otherDevices | - |
sync.refresh() | () => Promise<boolean> | - | - |
wallet | object | - | - |
wallet.agreedTo() | (party, purpose, noticeSha256) => Promise<boolean> | - | Whether the holder's consent to party for purpose covers the notice with this hash, and hasn't been withdrawn since. |
wallet.claims() | (credential) => Claims | - | The minimal claims a document supports today, e.g. age_over.18, without its details. |
wallet.clearUnanswered() | (id) => Promise<SecretCredential> | - | Forgets the devices a secret was declined by or never reached: its note says only where it is, and where it's still offered. |
wallet.consents() | () => Promise<ConsentRecord[]> | - | What the holder has agreed to (and withdrawn), newest first. |
wallet.credentials() | () => Promise<SdJwtVcCredential & object[]> | - | The credentials kivi can present, derived from its documents. |
wallet.deriveCredential() | (doc) => Promise<SdJwtVcCredential> | - | Self-issues the presentable credentials for a document: the claims it supports, each selectively disclosable, with how the document was checked visible to the verifier: a small batch, each signed by and bound to its own single-use key (so its issuer is that key too), so nothing ties one presentation to another, or to the holder's identity key. kivi can always issue more of its own: the batch is topped up when it runs out. |
wallet.document() | (id) => Promise<DocumentCredential | undefined> | - | - |
wallet.documents() | () => Promise<DocumentCredential[]> | - | - |
wallet.identity() | () => Promise<IdentityKey> | - | The holder's did:key, created on first use. |
wallet.keptAlsoOn() | (id, where) => Promise<SecretCredential> | - | Notes that another device now keeps a copy of a secret kept (or noted) here: added as each copy is made. |
wallet.markLeftTo() | (id, contact, at) => Promise<SecretCredential> | - | Notes a secret left to the beneficiary contact (prd.md §7.11, legacy), or no longer (at undefined). |
wallet.markRecoverable() | (id, at) => Promise<SecretCredential> | - | Marks a secret recoverable (prd.md §7.11: its value is in the secrets vault), or not (at undefined). |
wallet.offersDelivered() | (id, deliveries) => Promise<SecretCredential> | - | Notes how each offer of a secret went: handed over live, left in a drop box, or not at all (custody.ts). |
wallet.recordConsent() | (party, purpose, notice?, detail) => Promise<ConsentRecord> | - | Records that the holder agreed to notice from party, for purpose (and what went, and how). |
wallet.removeSecret() | (id) => Promise<void> | - | - |
wallet.requestErasure() | (party, fetchImpl) => Promise<{ outcome: "accepted" | "refused" | "unreachable" | "no-endpoint"; record: ConsentRecord; sent: number; }> | - | Asks party to erase what it received (prd.md §7.6): finds the erasure endpoint in its wellknown.id config, and sends one request per presentation made from this device, each signed with the key that bound it. Records what happened, and lets those keys go once the party has accepted. |
wallet.secrets() | () => Promise<SecretCredential[]> | - | The secrets kept here: names and kinds, never values (prd.md §7.9). |
wallet.withdrawConsent() | (party, purpose?, detail) => Promise<ConsentRecord> | - | Records that the holder withdrew their consent to party (for purpose, or everything), from now on. |
addDocument() | ( transport, key, options? ) => Promise<DocumentCredential> | - | Reads a passport or ID card over transport (NFC, a card reader, the virtual passport) and keeps it. key is the MRZ details, or the card access number (CAN) printed on ID cards. |
addSecret() | (s, where?) => Promise<SecretCredential> | - | Keeps a secret: here, sealed behind this device's gate (which may ask the holder), and/or recorded as kept on bonded devices already (custody.ts sends it). Never stored anywhere unsealed. |
mayAsk() | ( id, did, own ) => Promise<boolean> | - | Whether did may ask for this secret: the holder's own devices always; others only if it's shared with them. |
offerAnswered() | (bondId, answer) => Promise<SecretCredential | undefined> | - | An offered device's answer (custody.ts), from the bond it was offered over: kept (the offer becomes a copy kept there) or declined (noted, with why). Resolves the secret it was about, if any. |
openSecret() | (id) => Promise<Uint8Array<ArrayBufferLike>> | - | A secret's value: through the gate, which asks the holder each time on phones. |
prepareAnswer() | ( requestData, origin, credentialIds?, how? ) => Promise<{ asked: object[]; protocol: string; share: (declared?) => Promise<{ vp_token: Record<string, string[]>; }>; }> | - | - |
presentTo() | ( credentialId, paths, aud, nonce, how? ) => Promise<string> | - | Presents what a credential says to a contact (prd.md §7.14), as to a site but not to one: only paths, key-bound to aud (their device's did:key) and their nonce, so they can check it but not use it as their own (anyone shown it finds the binding names someone else). Recorded (present-to-contact); a single-use credential is spent. |
remove() | (id) => Promise<void> | - | - |
shareSecret() | (id, withDevices) => Promise<void> | - | Which devices of limited bonds and other people a secret is listed for (by did:key), besides the holder's own (prd.md §7.10). They see its name and kind, and may ask for it; the holder is asked each time. |
witnessDocument() | (doc, o) => Promise<{ count: number; witness: string; }> | - | Has a witness check a document's chip itself, and keeps the batch it issues, replacing any earlier batch from the same witness for this document. Each credential gets its own single-use key; the keys are made first, so the holder isn't holding the phone to the document while hardware makes them. withCard runs its argument once a card is there (NFC); connect opens the channel to the witness. |
witnesses | object | - | - |
witnesses.connect() | (endpoint) => Promise<WitnessConn> | - | - |
witnesses.discover() | (domain) => Promise<DiscoveredWitness> | - | A witness's config, from its domain's wellknown.id config. |
registerCredentials() | () => Promise<{ registered: string[]; supported: boolean; }> | - | Makes this wallet's credentials available to sites through the platform (the registry port): every verified document gets its presentable credentials first (documents read before credentials existed get theirs now). |