provared 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,7 +1,216 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.8.0 (1 November 2026)
4
+
5
+ Version 0.8.0 changes the library's browser part, `src/passkey-browser.js`, which a web page uses to have a person sign with a passkey. A new function, `signChallengeWithChosenPasskey`, lets a page whose browser has forgotten which passkey signed before ask the device to offer the passkeys it holds for the website; the page must then check what comes back against the key it expects. Every signing function now also says which passkey signed (`credentialId`). What changes for a user: every other signing function now refuses, before the device is asked, a passkey that does not name its identifier as text of at least one character, with a `PasskeyError` of code `cancelled` and the words "No passkey was named, so nothing was signed." A missing or non-text identifier already failed with that code, with other words; a passkey whose identifier was empty text was handed to the device, and now throws instead. The signing page uses all this to open as a small window for another page (the Provared application), sign a new permission, a renewal or a cancellation there, and hand the record back; the signing page is served at sign.prova.red and is not in the npm package. Nothing else in the library changes: no record's bytes, no rule of the checker, nothing in the Python version but its version number, so a book checks with 0.8.0 exactly as with 0.7.0. Beside the library, in this repository, with entries in the list below: `provared-mcp-executor` 0.2.0, with rules on the content of a tool call, already published on npm on 1 November 2026; and a reader of Agent Middleware's receipts, `provared-agent-middleware`, not published. The framework packages `provared-langchain` and `pydantic-ai-provared` stay at 0.2.0, unchanged.
6
+
7
+ - **Versions.** The library is 0.8.0, in `package.json` and `python/pyproject.toml`. The Hermes plugin (not published) asks for `provared>=0.4.0,<0.9`, where it asked for `<0.8`, which left 0.8.0 out; the test workflow checks that bound. `examples/frameworks/package-lock.json` gives the library's version as 0.8.0. No other package's range changes: the others' tests run against the repository's own library whatever range they state, and the ranges of the published `provared-mcp-executor` 0.2.0 (`^0.7.0`) and `provared-claude-code` 0.1.0 (`>=0.6.0 <0.8.0`) are left as published, since neither needs anything of 0.8.0. The README, the guide, the Python README and three pages say 0.8.0, and the guide gives the checking page's new fingerprint.
8
+
9
+ - **The signing page opened as a small window by another page** (the
10
+ Provared application, which signs nothing itself). `page/sign.html` and
11
+ `page/sign-page.js` take a request after `#request=` in the address: a
12
+ new permission, a renewal or a cancellation, with the fields to fill,
13
+ the earlier signed permission, the passkey's public key, the address to
14
+ hand the result back to, and a short text handed back unchanged. The
15
+ page trusts the earlier permission only once the library's checker has
16
+ confirmed its passkey signature, then shows what the new permission
17
+ changes against it, part by part. It shows the return address before
18
+ signing, and warns, asking for a second press, before a new passkey is
19
+ made, before an agent's key set is signed for the first time on that
20
+ device, before a passkey other than the earlier one signs, and where the
21
+ return address is not one of the application's own two addresses,
22
+ exactly (`https://app.prova.red:8443` and `https://app.prova.red`;
23
+ `http://localhost` is taken and always warned of). The warnings are
24
+ worked out again at every press, and a press signs only where every
25
+ warning that stands then was shown and confirmed; a passkey prompt that
26
+ fails, or a passkey this browser forgets, takes the confirmation back. A
27
+ passkey is made only where the warning that one will be made was among
28
+ those confirmed. Where the browser has forgotten which passkey signed
29
+ before, the device is asked to offer the passkeys it holds for the
30
+ website, and what it signs is kept only if the checker passes it with
31
+ the expected public key. A cancellation is signed only by the passkey
32
+ that signed the permission, at this page's own website name and
33
+ address: a request to cancel one signed elsewhere, or with a passkey for
34
+ another website name (a parent name included), is refused, and a
35
+ cancellation never makes a passkey. A cancellation for an address that
36
+ is not the application's asks for a second press too. The signed record
37
+ is sent by `postMessage` to the exact return address, and the page says
38
+ it was handed over only once that page answers; it closes once that page
39
+ answers, from the window that opened it and from the return address
40
+ exactly, that it kept the record (`{ provared: 'received', kind, state,
41
+ kept }`), and stays open with the file offered where it says it did not,
42
+ or says nothing within ten seconds. With no window that opened it, the
43
+ page offers the file first, then a button that goes back with the record
44
+ after `#signed=`. A signature that arrives after the permission was
45
+ changed is not kept. A page shown inside another page still offers
46
+ nothing.
47
+ - `src/passkey-browser.js`: `signChallengeWithChosenPasskey(challenge,
48
+ rpId)` asks the device to offer the passkeys it holds for the website,
49
+ for a caller that checks the answer against the key it expects; the
50
+ answer of every signing function now names the passkey's identifier
51
+ (`credentialId`). Every other function still refuses a passkey with no
52
+ identifier, so that no caller is offered a choice it did not ask for.
53
+ - Tests: `test/sign-request.test.mjs` (the request, the return address,
54
+ what changed, the messages each way) and `test/sign-window.test.mjs`
55
+ (the window driven in a browser with a virtual passkey, at phone and
56
+ desktop width: a new permission, a renewal and a cancellation handed
57
+ back; the wrong passkey refused; the answer that the record was not
58
+ kept, and no answer; the way back by a link for all three kinds; a
59
+ request that cannot be read; a framed page),
60
+ `test/sign-window-review.test.mjs` (the cases an independent review
61
+ found, at made-up https addresses: a failed passkey prompt, a passkey
62
+ forgotten between two presses, a cancellation for a parent website name
63
+ or another address, a cancellation for an unknown address, a record
64
+ sent to a page at another address, an answer from another window, a
65
+ change while the passkey is asked, a cancellation by another passkey)
66
+ and `test/passkey-browser-guard.test.mjs` (a passkey with no identifier
67
+ is refused before the device is asked).
68
+ - **After an independent re-check of the signing window, 1 November
69
+ 2026:** once a cancellation asked for by a request has been signed and
70
+ handed back (or offered to take back by a link), the "sign the
71
+ cancellation" button stays off: while the page that asked waits, after
72
+ it says it did not keep it, and after no answer. Before, it was switched
73
+ on again, and a second press signed a second cancellation with no new
74
+ warning. The file stays offered; a new request starts the page afresh.
75
+ Held by `test/sign-window.test.mjs`.
76
+
77
+ - **`provared-mcp-executor` 0.2.0** (published on npm on 1 November 2026
78
+ and listed in the official MCP Registry as
79
+ `io.github.provared/mcp-executor`; the library stays at 0.7.0, and the
80
+ executor still asks for `^0.7.0`). It carries the rules
81
+ on the content of a change, below (choices X56 to X77), and names itself
82
+ for the official MCP Registry: `package.json` gains
83
+ `"mcpName": "io.github.provared/mcp-executor"`, and
84
+ `mcp-executor/server.json` describes the package for the registry, with
85
+ the command line `stdio --config <settings file>` (choices X78 to X81 in
86
+ `mcp-executor/DESIGN.md`). `server.json` is not in the npm package; the
87
+ registry's publishing tool reads it from the folder. Beside it,
88
+ `mcp-executor/demo/` (not in the package): the executor in front of a
89
+ made-up tool server with two harmless tools, set up on its first start
90
+ with a permission signed by the library's development stand-in for a
91
+ passkey, so that a directory of MCP servers can start it with no
92
+ settings and no secret; a `Dockerfile` on the official `node` image,
93
+ pinned by digest; its records prove nothing about anyone, as its README
94
+ says (choices X82 to X89). One new test starts it as a real process.
95
+ After an independent review (choices X90 to X99): the README and the
96
+ design say that only an Owner of the organisation may publish to the
97
+ registry, with a token that can read its members, and only after the
98
+ npm version is out; the demonstration uses only an empty folder or one
99
+ it marked as its own, keeps each set-up in a folder of its own and never
100
+ renames or empties a folder, writes its paths afresh on every start (so
101
+ it survives a move or a new Node.js), lets two starts at once on an
102
+ empty folder each set up, says plainly when a folder cannot be written,
103
+ and its server compares the made-up credential's value; the container
104
+ is built from four named files, with a packed executor handed over as
105
+ a context of its own and never copied in. Four more tests. After a
106
+ second, narrow review (choice X100): an empty mark left by a start that
107
+ was stopped no longer refuses the folder for good, a file error inside
108
+ the folder gets the same plain words, and a name that is a file is said
109
+ to be one. Two more tests.
110
+ - **The MCP executor tests rules on the content of a change before a
111
+ call is let through** (F-157, F-158; `mcp-executor/rules.mjs`; choices
112
+ X56 to X70 in `mcp-executor/DESIGN.md`). A permission allows kinds of
113
+ action; being allowed to change a file is not being allowed to change
114
+ everything the file controls. The new setting `contentRules` names a
115
+ JSON file of rules: each names a tool, says which calls it applies to
116
+ (`when`: conditions on the arguments), where the proposed content is
117
+ and how to read it (`content`: a JSON Pointer, as JSON text or as plain
118
+ data) and what must hold in it (`test`: `equals`, `oneOf`, `absent`,
119
+ `matches` a plain glob, each at a JSON Pointer, with `orAbsent`). A rule
120
+ with no `test` refuses every call it applies to, which is how a tool
121
+ that carries only a partial edit is closed: the executor reads no file
122
+ and keeps no content. A call a rule refuses (`content-rule`), or whose
123
+ content the rule cannot read exactly (`content-unreadable`: not JSON, a
124
+ member named twice or twice once folded, a number beyond 2^53 - 1,
125
+ nothing at the pointer, not text, a text too long to match), is not
126
+ sent; the model is told which rule and what it asked for, never a value
127
+ from the arguments, and a denial is written. Every receipt and denial
128
+ names `executor.rules`, the SHA-256 of the rules file's parsed content
129
+ in the one form of RFC 8785; a denial by a rule also names
130
+ `executor.rule`, the fingerprint of the rule's name; both are labels.
131
+ The person puts the same fingerprint into the permission's
132
+ `agent.software` (`keys` prints the entry); where the permission states
133
+ software and the rules in force are not among it, the executor does not
134
+ start; where it states nothing, it warns. `check` reports the rules and
135
+ whether the permission states them; `compare` reports which rules
136
+ fingerprints the records name and whether a slip states each. The
137
+ README says plainly what the rules can never promise: an edit by
138
+ another route, a tool whose arguments do not show the resulting file, a
139
+ file type the executor cannot read, a pattern that matches characters
140
+ rather than files. Content in YAML, TOML or line-based forms is later
141
+ work. No record and no rule of the format changes. 12 new tests, among
142
+ them a label change let through and the same edit with a hidden setting
143
+ switched on refused.
144
+ After an independent review (choices X71 to X77): with `unlisted`
145
+ `forward`, a content rule for a tool that `tools` does not name stops
146
+ the start, since such a call was sent on before any content rule was
147
+ tested and the warning said the opposite; a permission whose
148
+ `agent.software` states rules on content (an entry named `Content rules
149
+ of …`) stops the start where the settings name no rules file, and
150
+ `compare` lists the executor's receipts and denials under such a slip
151
+ that name no rules file (`withoutRules`); a `/` or a `\` in a pattern
152
+ matches either separator, as promised, so `**/settings.json` matches
153
+ `C:\proj\settings.json`; a rules file holds at most 20,000 pattern parts
154
+ in all, which keeps one call to about a quarter of a second where a
155
+ chosen file took 9.6 seconds; the file is decoded as strict UTF-8; a
156
+ JSON Pointer with a `~` not followed by `0` or `1` is refused. Four more
157
+ limits are stated in the README: a `when` value that is not text does
158
+ not match; a member in other capitals in the content passes an
159
+ `absent` or `orAbsent` test; a path with a trailing full stop is another
160
+ text; JSON text inside a JSON string is not read. 7 new tests.
161
+ - **A reader of another project's receipts: Agent Middleware (AMW)**,
162
+ `integrations/agent-middleware/` (`provared-agent-middleware` 0.1.0, not
163
+ published): the first of the plan's readers of the closest other
164
+ projects' receipts. It checks an AMW permit or receipt by the gateway's
165
+ published Ed25519 key (the key found by `kid`, its status read; an
166
+ envelope compared with the signed content; AMW's own six answers,
167
+ reproduced for every one of its 96 published test cases, which are
168
+ copied into `test/vectors/` under their Apache License 2.0 with a notice
169
+ of where they came from), maps each verified receipt onto the fields
170
+ the checker compares (the tool as the action, `credits_charged` as the
171
+ amount in a unit and scale the reader states, `created_at` as the time,
172
+ `permit_id` as the permit it names), and judges a set of receipts
173
+ against a Provared slip that names the AMW gateway in `with`: the
174
+ checker's own codes where they apply (`action-not-allowed`,
175
+ `prohibited`, `outside-valid-time`, `over-limit`, `over-each-limit`,
176
+ `over-count-limit`, `over-period-limit`, `amount-missing`,
177
+ `approval-missing`), with words that say "AMW receipt"; codes of its
178
+ own (`amw-permit-…`) where only the AMW permit can be compared; and a
179
+ stated list of what cannot be judged (no chain, so omission and cut
180
+ ends do not show; no countersignature; no signature of the person on
181
+ the AMW permit; approvals by identifier only; which agent; with whom).
182
+ A denied AMW receipt is shown as the gateway's refusal and never
183
+ counted against the agent; a receipt that does not verify is not shown.
184
+ `receiptDocument` carries an AMW receipt by its fingerprint in a
185
+ Provared receipt's `details` under the name `agent-middleware.receipt`.
186
+ A command, `provared-agent-middleware verify | judge`, with the
187
+ checker's exit codes. Written from AMW's published data and the
188
+ standards alone; no AMW program was read or run. Its tests run in the
189
+ test workflow beside the other packages.
190
+ - **The AMW reader after an independent review**, each fix held by a
191
+ test (`test/review.test.mjs`): a slip's countersignature condition, or
192
+ an approval named by identifier only, is listed on the receipt it
193
+ applies to (`notJudged`), and such a receipt is never said to be within
194
+ the slip (`withinSlip` is `null`, not known) nor gives exit code 0
195
+ (before, both gave "within" and 0); a P-256 key over content that says
196
+ "Ed25519" reads `unsupported` (before, `verified`); signed text that is
197
+ not well-formed Unicode, names a member twice in one object, or gives a
198
+ `kid` that is not text is `malformed`; times are compared to the
199
+ nanosecond (before, cut to milliseconds, so two receipts 3,599.9996
200
+ seconds apart fell in different hours); a receipt handed over twice is
201
+ counted once and listed as a duplicate; a receipt that fails its check
202
+ shows no identifier (the envelope's is not signed), only its place; the
203
+ command shows control and invisible characters as a mark, and escapes
204
+ them in `--json`; `verify` loads no library, and the README's `judge`
205
+ command works from a copy of the repository; `cannotShow` also states
206
+ that cancellations cannot be handed over, that outcomes other than
207
+ success are left out of totals, and that retired keys check receipts
208
+ of any date. The package no longer pins a development copy of
209
+ `provared` 0.6.0, which its peer range excludes.
210
+
3
211
  ## 0.7.0 (1 November 2026)
4
212
 
213
+
5
214
  Version 0.7.0 makes three more document names part of the format (section 27 of the format description: `provared.tool-name`, `provared.tool-call-id` and `provared.tool-result`), and lets whoever checks a record name the addresses at which a permission must have been signed (`issuerOrigins`, Python `issuer_origins`, `--origin` on the command line, and a box on the checking page), so that a permission that another page under the passkey's website name had the passkey sign, by presenting it as a sign-in, is refused. Beside the library, two programs are published on npm for the first time, each at 0.1.0: `provared-mcp-executor`, an executor for MCP tool servers, which holds the tool servers' credentials, refuses a tool call the permission does not allow, and countersigns each receipt with keys of its own; and `provared-claude-code`, the recorder beside Claude Code, which can now also be installed as a Claude Code plugin. Releases are now published from the author's signed tag by a GitHub workflow, and each npm version waits for the author's approval with a passkey. What a reader must know: no record's bytes change, and a book written by 0.6.0 checks as it did, since 0.6.0 refused the three new names and so never wrote them; but a book that names any of the three new names checks in full only with a checker of 0.7.0 or later, because a checker of 0.5.0 or 0.6.0 refuses it (`bad-field`, as for every `provared.` name it does not know) and one of 0.4.0 or earlier reads the names as labels. The MCP executor writes two of them in every receipt, so its books need 0.7.0. The framework packages `provared-langchain` and `pydantic-ai-provared` stay at 0.2.0, unchanged: they ask for `provared` 0.6.0 or later, and what they write is the same with 0.7.0.
6
215
 
7
216
  - **Versions.** The library is 0.7.0, in `package.json` and `python/pyproject.toml`. Ranges on the library: `provared-mcp-executor` and the OpenTelemetry bridge (not published) now ask for `^0.7.0`, where they asked for `>0.6.0 <0.8.0`; the recorder beside Claude Code, the gateway and the sealer (neither of the last two published) ask for `>=0.6.0 <0.8.0`, where they asked for `^0.6.0`, which left 0.7.0 out (the recorder's `package-lock.json`, which a Claude Code plugin installs from, still holds 0.6.0, which the new range accepts, and the plugin's test of that lockfile now takes a range of that form as well as a caret range); the Hermes plugin (not published) asks for `>=0.4.0,<0.8`, where it asked for `<0.7`. The README and the guide name the two packages now on npm, with their install lines.
package/README.md CHANGED
@@ -171,7 +171,7 @@ each part protects against, is in
171
171
 
172
172
  ## Status
173
173
 
174
- **Version 0.7.0, a draft.** Published as it is, by one author in their
174
+ **Version 0.8.0, a draft.** Published as it is, by one author in their
175
175
  own time, built with AI tools since 3 October 2026; fixes as time
176
176
  allows. The code has been through more than 80 rounds of review by AI reviewers,
177
177
  each reviewer a fresh session given the code, the documents and a brief
package/docs/guide.md CHANGED
@@ -6,7 +6,7 @@ Everything about the format, the library, the checker, the stub writer beside an
6
6
 
7
7
  ## Status
8
8
 
9
- **Version 0.7.0, a draft.** Published as it is, by one author in their
9
+ **Version 0.8.0, a draft.** Published as it is, by one author in their
10
10
  own time; fixes as time allows. The format may still change, so do not
11
11
  rely on a draft record staying checkable.
12
12
 
@@ -153,9 +153,9 @@ be loaded from anywhere. The tool prints the file's SHA-256 fingerprint,
153
153
  so that a copy can be compared with it. (Tried on 8 October 2026 in the
154
154
  three browser builds this repository is tested with, and on 13 October
155
155
  2026 in Chrome 155, Edge 155 and Brave 155.) The file for
156
- version 0.7.0 is attached to the release on GitHub. Its SHA-256
156
+ version 0.8.0 is attached to the release on GitHub. Its SHA-256
157
157
  fingerprint is
158
- `c7b3d5fe1b9168628fc91308c7f952b970c05b3abeb908a132b8b2b78aaab1b5`.
158
+ `f9f2b6d747de66d7330dc2e7d817991e21208e16571f7f5d4e913d2c29ad4174`.
159
159
 
160
160
  **Run the demonstration in a browser.**
161
161
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "provared",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Proof of what an AI agent was allowed to do, and what it then did. A passkey-signed permission with limits a machine can check, a signed receipt for each action, and a free checker. Evidence, not a verdict.",
5
5
  "author": "Pavel Izmaylov",
6
6
  "license": "Apache-2.0 AND CC-BY-4.0",
package/page/style.css CHANGED
@@ -151,3 +151,10 @@ details.more textarea { width: 100%; box-sizing: border-box; font-family: ui-mon
151
151
 
152
152
  /* The mark: a permission slip with a signature, beside a heading or the site's name. */
153
153
  .mark { vertical-align: -0.2em; margin-right: 0.4em; }
154
+
155
+ /* The signing page: the warnings before a passkey is asked, and what a
156
+ renewal changes against the earlier permission. */
157
+ .warnings { margin: 0.8rem 0; padding: 0.6rem 0.9rem 0.6rem 2rem; border: 1px solid var(--bad); border-radius: 0.5rem; }
158
+ .warnings li { margin: 0.3rem 0; }
159
+ dt.changed { color: var(--seal); font-weight: 600; }
160
+ #cancel-of, #issuer-name { max-width: 100%; box-sizing: border-box; }
@@ -17,4 +17,6 @@ export function signSlipWithPasskey(fields: Omit<SlipFields, 'issuer'>, passkey:
17
17
  export function approveWithPasskey(request: Request & { slip: Fingerprint; when?: number | Date }, passkey: StoredPasskey): Promise<SignedRecord>;
18
18
  export function cancelWithPasskey(request: { slip: Fingerprint; when?: number | Date; id?: Base64url }, passkey: StoredPasskey): Promise<SignedRecord>;
19
19
  /** Sign the challenge of anything prepared for a passkey; hand the result to the matching assemble function. */
20
- export function signChallengeWithPasskey(challenge: Uint8Array, passkey: StoredPasskey): Promise<Assertion>;
20
+ export function signChallengeWithPasskey(challenge: Uint8Array, passkey: StoredPasskey): Promise<Assertion & { credentialId: string }>;
21
+ /** Sign a challenge with a passkey the person chooses from those the device holds for the website; check the answer against the key you expect before relying on it. */
22
+ export function signChallengeWithChosenPasskey(challenge: Uint8Array, rpId: string): Promise<Assertion & { credentialId: string }>;
@@ -87,15 +87,24 @@ export async function createPasskey({ name, site }) {
87
87
  }
88
88
 
89
89
  // Ask the passkey to sign a challenge: the device asks the person first.
90
- async function signedBy(passkey, challenge, refused) {
90
+ // Only where the caller asks for it ("choose"), and names no identifier (a
91
+ // passkey this browser has forgotten), the device offers every passkey it
92
+ // holds for the website and the person chooses; the answer then says which
93
+ // was chosen, and the caller must check it against the key it expects
94
+ // before it relies on it. Everywhere else a passkey with no identifier is
95
+ // refused, so that no caller is offered a choice it did not ask for.
96
+ async function signedBy(passkey, challenge, refused, { choose = false } = {}) {
91
97
  const container = credentials();
98
+ if (!choose && (!passkey || typeof passkey.credentialId !== 'string' || !passkey.credentialId)) {
99
+ throw new PasskeyError('cancelled', 'No passkey was named, so nothing was signed.');
100
+ }
92
101
  let assertion;
93
102
  try {
94
103
  assertion = await container.get({
95
104
  publicKey: {
96
105
  challenge,
97
106
  rpId: passkey.rpId,
98
- allowCredentials: [{ type: 'public-key', id: fromBase64url(passkey.credentialId) }],
107
+ ...(!choose ? { allowCredentials: [{ type: 'public-key', id: fromBase64url(passkey.credentialId) }] } : {}),
99
108
  userVerification: 'required',
100
109
  },
101
110
  });
@@ -107,6 +116,7 @@ async function signedBy(passkey, challenge, refused) {
107
116
  authenticatorData: new Uint8Array(r.authenticatorData),
108
117
  clientDataJSON: new Uint8Array(r.clientDataJSON),
109
118
  signature: new Uint8Array(r.signature),
119
+ credentialId: toBase64url(new Uint8Array(assertion.rawId)),
110
120
  };
111
121
  }
112
122
 
@@ -169,3 +179,22 @@ export async function signChallengeWithPasskey(challenge, passkey) {
169
179
  credentials();
170
180
  return signedBy(passkey, challenge, 'Nothing was signed. The request was cancelled or the device refused it.');
171
181
  }
182
+
183
+ /**
184
+ * Sign a challenge with a passkey the person chooses, where this browser
185
+ * has forgotten which passkey it should ask (a passkey made on another
186
+ * device, or this browser's storage cleared). The device offers every
187
+ * passkey it holds for the website, and the person chooses one; nothing
188
+ * new is made. What comes back names the passkey chosen by its identifier,
189
+ * but not its public key: the caller must put the answer into the record
190
+ * and check it with the library's checker against the key it expects, and
191
+ * only then remember the identifier beside that key.
192
+ *
193
+ * @param {Uint8Array} challenge the "challenge" of what was prepared
194
+ * @param {string} rpId the website the passkey belongs to (this page's hostname)
195
+ * @returns {Promise<{authenticatorData: Uint8Array, clientDataJSON: Uint8Array, signature: Uint8Array, credentialId: string}>}
196
+ */
197
+ export async function signChallengeWithChosenPasskey(challenge, rpId) {
198
+ credentials();
199
+ return signedBy({ rpId }, challenge, 'Nothing was signed. The request was cancelled, or this device holds no passkey for this website.', { choose: true });
200
+ }