@flow-industries/id 0.26.4 → 0.26.5
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/contracts/v1/sdk-exports.json +65 -0
- package/dist/sdk/client/index.d.ts +5 -1
- package/dist/sdk/client/index.js +3 -0
- package/dist/sdk/client/note-transport.d.ts +15 -0
- package/dist/sdk/client/note-transport.js +104 -0
- package/dist/sdk/client/passkey-prf.d.ts +8 -0
- package/dist/sdk/client/passkey-prf.js +67 -0
- package/dist/sdk/client/session.d.ts +2 -0
- package/dist/sdk/client/session.js +23 -0
- package/dist/sdk/types/atproto.d.ts +2 -0
- package/dist/sdk/types/index.d.ts +2 -1
- package/dist/sdk/types/note-transport.d.ts +140 -0
- package/dist/sdk/types/note-transport.js +0 -0
- package/dist/sdk/types/sdk.d.ts +5 -0
- package/package.json +1 -1
|
@@ -197,6 +197,11 @@
|
|
|
197
197
|
"type": false,
|
|
198
198
|
"value": true
|
|
199
199
|
},
|
|
200
|
+
{
|
|
201
|
+
"name": "createNoteTransport",
|
|
202
|
+
"type": false,
|
|
203
|
+
"value": true
|
|
204
|
+
},
|
|
200
205
|
{
|
|
201
206
|
"name": "createProfileButton",
|
|
202
207
|
"type": false,
|
|
@@ -252,6 +257,11 @@
|
|
|
252
257
|
"type": false,
|
|
253
258
|
"value": true
|
|
254
259
|
},
|
|
260
|
+
{
|
|
261
|
+
"name": "evaluatePasskeyPrf",
|
|
262
|
+
"type": false,
|
|
263
|
+
"value": true
|
|
264
|
+
},
|
|
255
265
|
{
|
|
256
266
|
"name": "fieldsCoveredBySubjects",
|
|
257
267
|
"type": false,
|
|
@@ -347,6 +357,11 @@
|
|
|
347
357
|
"type": false,
|
|
348
358
|
"value": true
|
|
349
359
|
},
|
|
360
|
+
{
|
|
361
|
+
"name": "getConnectedPasskey",
|
|
362
|
+
"type": false,
|
|
363
|
+
"value": true
|
|
364
|
+
},
|
|
350
365
|
{
|
|
351
366
|
"name": "getFlow",
|
|
352
367
|
"type": false,
|
|
@@ -427,6 +442,46 @@
|
|
|
427
442
|
"type": false,
|
|
428
443
|
"value": true
|
|
429
444
|
},
|
|
445
|
+
{
|
|
446
|
+
"name": "NoteBlob",
|
|
447
|
+
"type": true,
|
|
448
|
+
"value": false
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
"name": "NoteCollection",
|
|
452
|
+
"type": true,
|
|
453
|
+
"value": false
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
"name": "NoteOperation",
|
|
457
|
+
"type": true,
|
|
458
|
+
"value": false
|
|
459
|
+
},
|
|
460
|
+
{
|
|
461
|
+
"name": "NoteRecord",
|
|
462
|
+
"type": true,
|
|
463
|
+
"value": false
|
|
464
|
+
},
|
|
465
|
+
{
|
|
466
|
+
"name": "NoteResponses",
|
|
467
|
+
"type": true,
|
|
468
|
+
"value": false
|
|
469
|
+
},
|
|
470
|
+
{
|
|
471
|
+
"name": "NoteStoredRecord",
|
|
472
|
+
"type": true,
|
|
473
|
+
"value": false
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
"name": "NoteTransportError",
|
|
477
|
+
"type": true,
|
|
478
|
+
"value": true
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
"name": "NoteVaultHeader",
|
|
482
|
+
"type": true,
|
|
483
|
+
"value": false
|
|
484
|
+
},
|
|
430
485
|
{
|
|
431
486
|
"name": "NotificationCounts",
|
|
432
487
|
"type": true,
|
|
@@ -462,6 +517,16 @@
|
|
|
462
517
|
"type": true,
|
|
463
518
|
"value": false
|
|
464
519
|
},
|
|
520
|
+
{
|
|
521
|
+
"name": "PasskeyPrfError",
|
|
522
|
+
"type": true,
|
|
523
|
+
"value": true
|
|
524
|
+
},
|
|
525
|
+
{
|
|
526
|
+
"name": "PasskeyPrfOptions",
|
|
527
|
+
"type": true,
|
|
528
|
+
"value": false
|
|
529
|
+
},
|
|
465
530
|
{
|
|
466
531
|
"name": "ProfileButtonHandle",
|
|
467
532
|
"type": true,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { defaultIdHost, isLocalHostname } from "../id-host";
|
|
2
|
-
export type { AccessKeyOptions, ActionCatalogEntry, ActionCatalogResponse, ActionCurve, ActionEventRequest, ActionEventResponse, ActionSubjectRef, ActionSurface, ActionsApi, ActionTransitionKind, ActiveAction, ActiveActionResponse, ActiveSessionConflict, AdditionalSession, Address, AtprotoApi, AtprotoResolution, AtprotoResolutionFailure, AtprotoResolveOptions, BrowserAccount, BrowserAccounts, CatalogFieldRef, ClockAnchor, ConnectCapabilities, ConnectResponse, CreateFlowOptions, CreateStudySubjectInput, CurrentAction, DialogHost, FinishActionRequest, FinishActionResponse, FinishedSummary, Flow, FlowCredential, FlowSessionState, FlowState, FlowUser, FlowWidgetHandle, FlowWidgetName, FocusApi, FocusPhase, FocusSessionEvent, FocusSessionState, ListStudySessionsOptions, ListStudySubjectsOptions, LoginOptions, MarkNotificationsReadInput, MethodName, MountFlowWidgetOptions, MountProfileOptions, NotificationCounts, NotificationEntry, NotificationPage, NotificationReadResult, NotificationRefusal, OpenProfileOptions, ProfileButtonHandle, ProfilePosition, RoomMemberEntry, Session, StartActionInput, StartActionResponse, StartActionResult, StartFocusRequest, StudyApi, StudyCatalog, StudyCategory, StudyCategoryTotals, StudyField, StudyRange, StudySearchHit, StudySessionEntry, StudySessionPage, StudySubject, StudySubjectList, StudySubjectRefusal, StudySubjectRemovalResponse, StudySubjectResponse, StudySubjectTotals, StudySummary, SwitchAccountOptions, UpdateStudySubjectInput, UserActionSurface, XpEstimateContext, XpMode, } from "../types";
|
|
2
|
+
export type { AccessKeyOptions, ActionCatalogEntry, ActionCatalogResponse, ActionCurve, ActionEventRequest, ActionEventResponse, ActionSubjectRef, ActionSurface, ActionsApi, ActionTransitionKind, ActiveAction, ActiveActionResponse, ActiveSessionConflict, AdditionalSession, Address, AtprotoApi, AtprotoResolution, AtprotoResolutionFailure, AtprotoResolveOptions, BrowserAccount, BrowserAccounts, CatalogFieldRef, ClockAnchor, ConnectCapabilities, ConnectResponse, CreateFlowOptions, CreateStudySubjectInput, CurrentAction, DialogHost, FinishActionRequest, FinishActionResponse, FinishedSummary, Flow, FlowCredential, FlowSessionState, FlowState, FlowUser, FlowWidgetHandle, FlowWidgetName, FocusApi, FocusPhase, FocusSessionEvent, FocusSessionState, ListStudySessionsOptions, ListStudySubjectsOptions, LoginOptions, MarkNotificationsReadInput, MethodName, MountFlowWidgetOptions, MountProfileOptions, NotificationCounts, NotificationEntry, NotificationPage, NotificationReadResult, NotificationRefusal, OpenProfileOptions, PasskeyPrfOptions, ProfileButtonHandle, ProfilePosition, RoomMemberEntry, Session, StartActionInput, StartActionResponse, StartActionResult, StartFocusRequest, StudyApi, StudyCatalog, StudyCategory, StudyCategoryTotals, StudyField, StudyRange, StudySearchHit, StudySessionEntry, StudySessionPage, StudySubject, StudySubjectList, StudySubjectRefusal, StudySubjectRemovalResponse, StudySubjectResponse, StudySubjectTotals, StudySummary, SwitchAccountOptions, UpdateStudySubjectInput, UserActionSurface, XpEstimateContext, XpMode, } from "../types";
|
|
3
|
+
export type { NoteBlob, NoteCollection, NoteOperation, NoteRecord, NoteResponses, NoteStoredRecord, NoteVaultHeader, } from "../types/note-transport";
|
|
3
4
|
export { consistencyCurve, estimateActionXp, FLOW_SCORE_MAX, flowMultiplier, } from "../xp/curve";
|
|
4
5
|
export { ActionsRequestError, createActionsApi, isActiveSessionConflict, } from "./actions";
|
|
5
6
|
export { AtprotoRequestError, createAtprotoApi } from "./atproto-resolver";
|
|
@@ -8,10 +9,13 @@ export { createDialogHost } from "./dialog-host";
|
|
|
8
9
|
export { createFlowWidget } from "./flow-widget";
|
|
9
10
|
export { actionHeadline, anchorFor, catalogFieldIndex, createFocusApi, elapsedSeconds, fieldsCoveredBySubjects, focusSessionReducer, formatElapsed, hitLabel, INITIAL_FOCUS_STATE, MEDITATION_SOURCE, matchScore, normalizeSearchText, REANCHOR_TOLERANCE_SECONDS, recentSubjects, STUDY_SOURCE, searchStudy, shouldReanchor, } from "./focus";
|
|
10
11
|
export { METHODS } from "./methods";
|
|
12
|
+
export { createNoteTransport, NoteTransportError } from "./note-transport";
|
|
11
13
|
export { closeProfile, openProfile } from "./open-profile";
|
|
14
|
+
export { evaluatePasskeyPrf, PasskeyPrfError } from "./passkey-prf";
|
|
12
15
|
export { createProfileButton } from "./profile-button";
|
|
13
16
|
export type { ReportOperation, ReportRequest, ReportResponse } from "./reports";
|
|
14
17
|
export { createReportsApi, ReportRequestError } from "./reports";
|
|
15
18
|
export { createRoomsApi, RoomsRequestError } from "./rooms";
|
|
19
|
+
export { getConnectedPasskey } from "./session";
|
|
16
20
|
export { createStaticFlow } from "./static-flow";
|
|
17
21
|
export { createStudyApi, StudyRequestError } from "./study";
|
package/dist/sdk/client/index.js
CHANGED
|
@@ -7,9 +7,12 @@ export { createDialogHost } from "./dialog-host";
|
|
|
7
7
|
export { createFlowWidget } from "./flow-widget";
|
|
8
8
|
export { actionHeadline, anchorFor, catalogFieldIndex, createFocusApi, elapsedSeconds, fieldsCoveredBySubjects, focusSessionReducer, formatElapsed, hitLabel, INITIAL_FOCUS_STATE, MEDITATION_SOURCE, matchScore, normalizeSearchText, REANCHOR_TOLERANCE_SECONDS, recentSubjects, STUDY_SOURCE, searchStudy, shouldReanchor, } from "./focus";
|
|
9
9
|
export { METHODS } from "./methods";
|
|
10
|
+
export { createNoteTransport, NoteTransportError } from "./note-transport";
|
|
10
11
|
export { closeProfile, openProfile } from "./open-profile";
|
|
12
|
+
export { evaluatePasskeyPrf, PasskeyPrfError } from "./passkey-prf";
|
|
11
13
|
export { createProfileButton } from "./profile-button";
|
|
12
14
|
export { createReportsApi, ReportRequestError } from "./reports";
|
|
13
15
|
export { createRoomsApi, RoomsRequestError } from "./rooms";
|
|
16
|
+
export { getConnectedPasskey } from "./session";
|
|
14
17
|
export { createStaticFlow } from "./static-flow";
|
|
15
18
|
export { createStudyApi, StudyRequestError } from "./study";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { AtprotoApi, AtprotoResolution } from "../types/atproto";
|
|
2
|
+
import type { NoteBlob, NoteOperation, NoteResponses } from "../types/note-transport";
|
|
3
|
+
export declare class NoteTransportError extends Error {
|
|
4
|
+
readonly code: string;
|
|
5
|
+
readonly status: number;
|
|
6
|
+
constructor(code: string, status: number);
|
|
7
|
+
}
|
|
8
|
+
/** Ciphertext-only Auth transport; the browser never receives provider tokens or DPoP keys. */
|
|
9
|
+
export declare function createNoteTransport(host: string, getToken: () => Promise<string | null>, getUserId: () => string | null, getSessionVersion: () => number, resolver: AtprotoApi, expectedIdentity: Pick<AtprotoResolution, "did" | "identityVersion">): {
|
|
10
|
+
records<T extends NoteOperation>(operation: T, signal?: AbortSignal): Promise<NoteResponses[T["method"]]>;
|
|
11
|
+
download(cid: string, signal?: AbortSignal): Promise<Uint8Array<ArrayBuffer>>;
|
|
12
|
+
upload(bytes: Uint8Array<ArrayBuffer>, signal?: AbortSignal): Promise<{
|
|
13
|
+
blob: NoteBlob;
|
|
14
|
+
}>;
|
|
15
|
+
};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export class NoteTransportError extends Error {
|
|
3
|
+
code;
|
|
4
|
+
status;
|
|
5
|
+
constructor(code, status) {
|
|
6
|
+
super(code);
|
|
7
|
+
this.code = code;
|
|
8
|
+
this.status = status;
|
|
9
|
+
this.name = "NoteTransportError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/** Ciphertext-only Auth transport; the browser never receives provider tokens or DPoP keys. */
|
|
13
|
+
export function createNoteTransport(host, getToken, getUserId, getSessionVersion, resolver, expectedIdentity) {
|
|
14
|
+
const pinnedIdentity = { ...expectedIdentity };
|
|
15
|
+
async function request(action, body, signal) {
|
|
16
|
+
signal?.throwIfAborted();
|
|
17
|
+
const userId = getUserId();
|
|
18
|
+
const version = getSessionVersion();
|
|
19
|
+
if (!userId)
|
|
20
|
+
throw new NoteTransportError("SIGN_IN_REQUIRED", 401);
|
|
21
|
+
const unchanged = () => {
|
|
22
|
+
if (getUserId() !== userId || getSessionVersion() !== version)
|
|
23
|
+
throw new NoteTransportError("ACCOUNT_CHANGED", 409);
|
|
24
|
+
};
|
|
25
|
+
const resolution = await resolver.resolve({ freshness: "refresh", signal });
|
|
26
|
+
unchanged();
|
|
27
|
+
if (resolution.did !== pinnedIdentity.did ||
|
|
28
|
+
resolution.identityVersion !== pinnedIdentity.identityVersion) {
|
|
29
|
+
resolver.invalidate();
|
|
30
|
+
throw new NoteTransportError("ACCOUNT_CHANGED", 409);
|
|
31
|
+
}
|
|
32
|
+
if (resolution.lifecycle !== "active" ||
|
|
33
|
+
resolution.authorization !== "connected")
|
|
34
|
+
throw new NoteTransportError("RECONNECT_REQUIRED", 403);
|
|
35
|
+
const token = await getToken();
|
|
36
|
+
unchanged();
|
|
37
|
+
if (!token)
|
|
38
|
+
throw new NoteTransportError("SIGN_IN_REQUIRED", 401);
|
|
39
|
+
let response;
|
|
40
|
+
try {
|
|
41
|
+
response = await fetch(`${host}/api/atproto/note/${action}`, {
|
|
42
|
+
method: "POST",
|
|
43
|
+
headers: {
|
|
44
|
+
Authorization: `Bearer ${token}`,
|
|
45
|
+
"X-Flow-User-Id": userId,
|
|
46
|
+
"X-Flow-At-Did": pinnedIdentity.did,
|
|
47
|
+
"X-Flow-Identity-Version": pinnedIdentity.identityVersion,
|
|
48
|
+
"Content-Type": action === "upload"
|
|
49
|
+
? "application/octet-stream"
|
|
50
|
+
: "application/json",
|
|
51
|
+
},
|
|
52
|
+
body,
|
|
53
|
+
signal,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
signal?.throwIfAborted();
|
|
58
|
+
unchanged();
|
|
59
|
+
throw new NoteTransportError("PDS_UNAVAILABLE", 503);
|
|
60
|
+
}
|
|
61
|
+
const data = action === "download" && response.ok
|
|
62
|
+
? new Uint8Array(await response.arrayBuffer())
|
|
63
|
+
: await response.json().catch(() => null);
|
|
64
|
+
signal?.throwIfAborted();
|
|
65
|
+
unchanged();
|
|
66
|
+
if (!response.ok) {
|
|
67
|
+
const parsed = z.object({ code: z.string() }).safeParse(data);
|
|
68
|
+
const code = parsed.success ? parsed.data.code : "PDS_UNAVAILABLE";
|
|
69
|
+
if (code === "ACCOUNT_CHANGED" || code === "RECONNECT_REQUIRED")
|
|
70
|
+
resolver.invalidate();
|
|
71
|
+
throw new NoteTransportError(code, response.status);
|
|
72
|
+
}
|
|
73
|
+
const after = await resolver.resolve({ freshness: "refresh", signal });
|
|
74
|
+
unchanged();
|
|
75
|
+
if (after.did !== pinnedIdentity.did ||
|
|
76
|
+
after.identityVersion !== pinnedIdentity.identityVersion) {
|
|
77
|
+
resolver.invalidate();
|
|
78
|
+
throw new NoteTransportError("ACCOUNT_CHANGED", 409);
|
|
79
|
+
}
|
|
80
|
+
if (data instanceof Uint8Array)
|
|
81
|
+
return new Uint8Array(data);
|
|
82
|
+
const parsed = z.record(z.string(), z.unknown()).safeParse(data);
|
|
83
|
+
if (!parsed.success)
|
|
84
|
+
throw new NoteTransportError("INVALID_RESPONSE", 502);
|
|
85
|
+
// SAFETY: Auth validates method-specific ciphertext schemas and strips provider secrets; the SDK preserves those named contracts.
|
|
86
|
+
return parsed.data;
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
async records(operation, signal) {
|
|
90
|
+
// SAFETY: Auth validates the selected operation's named response schema.
|
|
91
|
+
return (await request("records", JSON.stringify(operation), signal));
|
|
92
|
+
},
|
|
93
|
+
async download(cid, signal) {
|
|
94
|
+
const result = await request("download", JSON.stringify({ cid }), signal);
|
|
95
|
+
if (!(result instanceof Uint8Array))
|
|
96
|
+
throw new NoteTransportError("INVALID_RESPONSE", 502);
|
|
97
|
+
return result;
|
|
98
|
+
},
|
|
99
|
+
async upload(bytes, signal) {
|
|
100
|
+
// SAFETY: Auth validates the upload response as a single standard octet-stream blob reference.
|
|
101
|
+
return (await request("upload", bytes, signal));
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FlowCredential } from "../types/auth";
|
|
2
|
+
import type { PasskeyPrfOptions } from "../types/sdk";
|
|
3
|
+
export declare class PasskeyPrfError extends Error {
|
|
4
|
+
readonly code: "PASSKEY_REQUIRED" | "PRF_UNAVAILABLE" | "ACCOUNT_CHANGED" | "INVALID_INPUT";
|
|
5
|
+
constructor(code: "PASSKEY_REQUIRED" | "PRF_UNAVAILABLE" | "ACCOUNT_CHANGED" | "INVALID_INPUT");
|
|
6
|
+
}
|
|
7
|
+
/** Evaluate only the connected passkey. Output is client-only key material: never serialize or log it. */
|
|
8
|
+
export declare function evaluatePasskeyPrf(getCredential: () => FlowCredential | null, getUserId: () => string | null, getSessionVersion: () => number, options: PasskeyPrfOptions): Promise<Uint8Array<ArrayBuffer>>;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export class PasskeyPrfError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
constructor(code) {
|
|
4
|
+
super(code);
|
|
5
|
+
this.code = code;
|
|
6
|
+
this.name = "PasskeyPrfError";
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
/** Evaluate only the connected passkey. Output is client-only key material: never serialize or log it. */
|
|
10
|
+
export async function evaluatePasskeyPrf(getCredential, getUserId, getSessionVersion, options) {
|
|
11
|
+
options.signal?.throwIfAborted();
|
|
12
|
+
const credential = getCredential();
|
|
13
|
+
const userId = getUserId();
|
|
14
|
+
const sessionVersion = getSessionVersion();
|
|
15
|
+
if (!credential || !userId)
|
|
16
|
+
throw new PasskeyPrfError("PASSKEY_REQUIRED");
|
|
17
|
+
if (options.input.byteLength !== 32 || !options.rpId)
|
|
18
|
+
throw new PasskeyPrfError("INVALID_INPUT");
|
|
19
|
+
let id;
|
|
20
|
+
try {
|
|
21
|
+
if (!/^[A-Za-z0-9_-]+$/.test(credential.id))
|
|
22
|
+
throw new Error();
|
|
23
|
+
id = Uint8Array.from(atob(credential.id.replace(/-/g, "+").replace(/_/g, "/")), (character) => character.charCodeAt(0));
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
throw new PasskeyPrfError("INVALID_INPUT");
|
|
27
|
+
}
|
|
28
|
+
const unchanged = () => {
|
|
29
|
+
if (getSessionVersion() !== sessionVersion ||
|
|
30
|
+
getUserId() !== userId ||
|
|
31
|
+
getCredential()?.id !== credential.id)
|
|
32
|
+
throw new PasskeyPrfError("ACCOUNT_CHANGED");
|
|
33
|
+
};
|
|
34
|
+
if (!globalThis.navigator?.credentials || !globalThis.PublicKeyCredential)
|
|
35
|
+
throw new PasskeyPrfError("PRF_UNAVAILABLE");
|
|
36
|
+
let assertion;
|
|
37
|
+
try {
|
|
38
|
+
assertion = await navigator.credentials.get({
|
|
39
|
+
publicKey: {
|
|
40
|
+
challenge: crypto.getRandomValues(new Uint8Array(32)),
|
|
41
|
+
rpId: options.rpId,
|
|
42
|
+
allowCredentials: [{ type: "public-key", id }],
|
|
43
|
+
userVerification: "required",
|
|
44
|
+
timeout: 60_000,
|
|
45
|
+
extensions: { prf: { eval: { first: options.input.slice().buffer } } },
|
|
46
|
+
},
|
|
47
|
+
signal: options.signal,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
options.signal?.throwIfAborted();
|
|
52
|
+
unchanged();
|
|
53
|
+
throw new PasskeyPrfError("PRF_UNAVAILABLE");
|
|
54
|
+
}
|
|
55
|
+
options.signal?.throwIfAborted();
|
|
56
|
+
unchanged();
|
|
57
|
+
if (!(assertion instanceof PublicKeyCredential))
|
|
58
|
+
throw new PasskeyPrfError("PRF_UNAVAILABLE");
|
|
59
|
+
const actualId = new Uint8Array(assertion.rawId);
|
|
60
|
+
if (actualId.length !== id.length ||
|
|
61
|
+
actualId.some((byte, i) => byte !== id[i]))
|
|
62
|
+
throw new PasskeyPrfError("PRF_UNAVAILABLE");
|
|
63
|
+
const result = assertion.getClientExtensionResults().prf?.results?.first;
|
|
64
|
+
if (!(result instanceof ArrayBuffer) || result.byteLength !== 32)
|
|
65
|
+
throw new PasskeyPrfError("PRF_UNAVAILABLE");
|
|
66
|
+
return new Uint8Array(result.slice(0));
|
|
67
|
+
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { Address, FlowCredential, FlowState, Store } from "../types";
|
|
2
|
+
/** Reads cached public passkey metadata only; this does not establish a signed-in session or evaluate PRF. */
|
|
3
|
+
export declare function getConnectedPasskey(): Promise<FlowCredential | null>;
|
|
2
4
|
/**
|
|
3
5
|
* Reads the active credential from IndexedDB and seeds the in-memory store
|
|
4
6
|
* with `{ credential, address }`. Run on every page load so signing operations
|
|
@@ -1,9 +1,32 @@
|
|
|
1
1
|
import * as OxAddress from "ox/Address";
|
|
2
2
|
import * as PublicKey from "ox/PublicKey";
|
|
3
|
+
import { z } from "zod";
|
|
3
4
|
import { hex0x } from "../hex";
|
|
4
5
|
import { idb } from "./idb";
|
|
5
6
|
import { initialFlowState } from "./store";
|
|
6
7
|
const CREDENTIAL_KEY = "flow.activeCredential";
|
|
8
|
+
const cachedCredentialSchema = z
|
|
9
|
+
.object({
|
|
10
|
+
id: z
|
|
11
|
+
.string()
|
|
12
|
+
.min(1)
|
|
13
|
+
.max(2048)
|
|
14
|
+
.regex(/^[A-Za-z0-9_-]+$/),
|
|
15
|
+
publicKey: z.string().regex(/^(?:0x)?(?:04)?[a-fA-F0-9]{128}$/),
|
|
16
|
+
})
|
|
17
|
+
.strict();
|
|
18
|
+
/** Reads cached public passkey metadata only; this does not establish a signed-in session or evaluate PRF. */
|
|
19
|
+
export async function getConnectedPasskey() {
|
|
20
|
+
if (!globalThis.indexedDB)
|
|
21
|
+
return null;
|
|
22
|
+
try {
|
|
23
|
+
const parsed = cachedCredentialSchema.safeParse(await idb.get(CREDENTIAL_KEY));
|
|
24
|
+
return parsed.success ? parsed.data : null;
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
7
30
|
/**
|
|
8
31
|
* Reads the active credential from IndexedDB and seeds the in-memory store
|
|
9
32
|
* with `{ credential, address }`. Run on every page load so signing operations
|
|
@@ -4,6 +4,7 @@ export type AtprotoStartRequest = {
|
|
|
4
4
|
intent: "login" | "link";
|
|
5
5
|
transaction?: string;
|
|
6
6
|
expectedUserId?: string;
|
|
7
|
+
noteConsent?: true;
|
|
7
8
|
};
|
|
8
9
|
export type AtprotoCompletion = {
|
|
9
10
|
user: {
|
|
@@ -15,6 +16,7 @@ export type AtprotoCompletion = {
|
|
|
15
16
|
linked: true;
|
|
16
17
|
};
|
|
17
18
|
export type AtprotoStatus = {
|
|
19
|
+
noteConsentEnabled?: boolean;
|
|
18
20
|
enabled: boolean;
|
|
19
21
|
connection: {
|
|
20
22
|
did: string;
|
|
@@ -16,6 +16,7 @@ export type { HostingQuotaAdmission, HostingQuotaLedger, HostingQuotaPolicy, Hos
|
|
|
16
16
|
export type { AccountProfileData } from "./landing";
|
|
17
17
|
export type * from "./managed-provisioning";
|
|
18
18
|
export type { Bridge, BridgeParameters, FlowAccount, FlowRemote, FlowRemoteConfig, FromWindowOptions, MessageResponse, Messenger, OneOf, Payload, QueuedRequest, ReadyOptions, RemoteFlowState, RemoteState, Schema, Storage, Topic, WithReady, } from "./messenger";
|
|
19
|
+
export type { NoteBlob, NoteCollection, NoteOperation, NoteRecord, NoteResponses, NoteStoredRecord, NoteTransportDeps, NoteVaultHeader, } from "./note-transport";
|
|
19
20
|
export type { MarkNotificationsReadInput, NotificationCounts, NotificationEntry, NotificationPage, NotificationReadResult, NotificationRefusal, } from "./notifications";
|
|
20
21
|
export type { OtpVerificationFailure, OtpVerificationResult, VerificationAdapter, } from "./otp";
|
|
21
22
|
export type { Call, ConnectCapabilities, ConnectResponse, MethodName, MethodParams, MethodResult, RestoreResponse, RpcRequest, SendCallsParams, SendCallsRequest, SendCallsResponse, SendTransactionParams, SendTransactionRequest, SendTransactionResponse, SignMessageRequest, SignMessageResponse, SignTypedDataRequest, SignTypedDataResponse, TransactionArgs, TypedData, TypedDataDomain, TypedDataField, } from "./protocol";
|
|
@@ -23,7 +24,7 @@ export { isPersonalSignParams, isSendCallsParams, isSendTransactionParams, } fro
|
|
|
23
24
|
export type { ReportOperation, ReportRequest, ReportResponse, ReportsApi, ReportTransport, } from "./reports";
|
|
24
25
|
export type { CreateRoomEventInput, RoomEventArchive, RoomEventAttendance, RoomEventFrequency, RoomEventInstance, RoomEventInterest, RoomEventInterestState, RoomEventList, RoomEventOccurrence, RoomEventRecurrence, RoomEventRoomRef, RoomEventRun, RoomEventSeries, RoomEventStatus, SetInterestInput, UpdateRoomEventInput, } from "./room-events";
|
|
25
26
|
export type { CreateRoomInput, GlobalRole, ModerationSubject, MyRooms, PlayerPositionReport, RoleChangeVerdict, RoomCapabilities, RoomCapability, RoomChannel, RoomDetail, RoomList, RoomMemberEntry, RoomMembers, RoomOccupancy, RoomOwner, RoomPlayerPosition, RoomPresenceEntry, RoomPresenceSnapshot, RoomRestrictionKind, RoomRole, RoomSummary, RoomSurfaceSettings, RoomsApi, RoomVisibility, StaffEntry, UpdateRoomInput, VerifyRoomContext, Viewer, VoiceDecisionReason, VoiceDecisionSubject, VoiceRoomDecision, } from "./rooms";
|
|
26
|
-
export type { AccessKeyOptions, AccessKeyPreparation, AccountMenuProps, Address, ColorScheme, CreateDialogHostOptions, CreateFlowOptions, DialogHost, DialogOpenOptions, FinalizeAccessKeyParams, Flow, FlowConnectorParameters, FlowCookieNames, FlowIdProviderProps, FlowProfileButtonProps, FlowSessionState, FlowState, FlowWidgetHandle, FlowWidgetName, FlowWidgetProps, Listener, LoginOptions, MountFlowWidgetOptions, MountProfileOptions, OpenProfileOptions, PrepareArgsWithAuth, PrepareTransactionRequestPhase, ProfileButtonHandle, ProfileButtonProps, ProfileMenuMountOptions, ProfilePosition, ResolveAccountParams, ResolvedAccessKeyOptions, RootCredential, SendCallsArgs, SendTransactionArgs, Session, SigningContext, SignMessageArgs, SignTypedDataArgs, Store, StoredAccessKey, SwitchAccountOptions, UseOpenProfileOptions, WagmiConnectCapabilities, WagmiConnectParams, } from "./sdk";
|
|
27
|
+
export type { AccessKeyOptions, AccessKeyPreparation, AccountMenuProps, Address, ColorScheme, CreateDialogHostOptions, CreateFlowOptions, DialogHost, DialogOpenOptions, FinalizeAccessKeyParams, Flow, FlowConnectorParameters, FlowCookieNames, FlowIdProviderProps, FlowProfileButtonProps, FlowSessionState, FlowState, FlowWidgetHandle, FlowWidgetName, FlowWidgetProps, Listener, LoginOptions, MountFlowWidgetOptions, MountProfileOptions, OpenProfileOptions, PasskeyPrfOptions, PrepareArgsWithAuth, PrepareTransactionRequestPhase, ProfileButtonHandle, ProfileButtonProps, ProfileMenuMountOptions, ProfilePosition, ResolveAccountParams, ResolvedAccessKeyOptions, RootCredential, SendCallsArgs, SendTransactionArgs, Session, SigningContext, SignMessageArgs, SignTypedDataArgs, Store, StoredAccessKey, SwitchAccountOptions, UseOpenProfileOptions, WagmiConnectCapabilities, WagmiConnectParams, } from "./sdk";
|
|
27
28
|
export type { GracefulShutdownCleanup, GracefulShutdownOptions, GracefulShutdownServer, GracefulShutdownSignal, ResolvedFlowSession, ResolveSessionOptions, SessionRouteOptions, SessionRouteResponse, SessionRouteSession, } from "./server";
|
|
28
29
|
export type { CosmeticOffer, PaintDescriptor, SettingDescriptor, Settings, SettingsMigration, StoredSettings, SurfaceRegistry, } from "./settings";
|
|
29
30
|
export type { CreateStudySubjectInput, ListStudySessionsInput, StudyCatalog, StudyCategory, StudyCategoryTotals, StudyField, StudyRange, StudySessionEntry, StudySessionPage, StudySessionsResult, StudySubject, StudySubjectCreation, StudySubjectList, StudySubjectRefusal, StudySubjectRemoval, StudySubjectRemovalResponse, StudySubjectTotals, StudySubjectUpdate, StudySummary, UpdateStudySubjectInput, } from "./study";
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import type { Context } from "hono";
|
|
2
|
+
import type { Caller } from "../caller";
|
|
3
|
+
import type { AtprotoResolution } from "./atproto";
|
|
4
|
+
import type { AtprotoMapping } from "./atproto-resolver";
|
|
5
|
+
export type NoteCollection = "game.flow.note.item" | "game.flow.note.tombstone" | "game.flow.note.vault";
|
|
6
|
+
export type NoteBlob = {
|
|
7
|
+
$type: "blob";
|
|
8
|
+
ref: {
|
|
9
|
+
$link: string;
|
|
10
|
+
};
|
|
11
|
+
mimeType: "application/octet-stream";
|
|
12
|
+
size: number;
|
|
13
|
+
};
|
|
14
|
+
export type NoteItemRecord = {
|
|
15
|
+
$type: "game.flow.note.item" | "game.flow.note.tombstone";
|
|
16
|
+
id: string;
|
|
17
|
+
revision: string;
|
|
18
|
+
envelope: {
|
|
19
|
+
version: 1;
|
|
20
|
+
nonce: string;
|
|
21
|
+
ciphertext: string;
|
|
22
|
+
};
|
|
23
|
+
blobs: NoteBlob[];
|
|
24
|
+
chunkHashes?: string[];
|
|
25
|
+
};
|
|
26
|
+
export type NoteVaultHeader = {
|
|
27
|
+
verifier: {
|
|
28
|
+
version: 1;
|
|
29
|
+
nonce: string;
|
|
30
|
+
ciphertext: string;
|
|
31
|
+
};
|
|
32
|
+
version: 1;
|
|
33
|
+
vault: string;
|
|
34
|
+
epoch: number;
|
|
35
|
+
access: {
|
|
36
|
+
keyId: string;
|
|
37
|
+
prfInput: number[];
|
|
38
|
+
wrapped: {
|
|
39
|
+
version: 1;
|
|
40
|
+
salt: string;
|
|
41
|
+
envelope: {
|
|
42
|
+
version: 1;
|
|
43
|
+
nonce: string;
|
|
44
|
+
ciphertext: string;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
}[];
|
|
48
|
+
};
|
|
49
|
+
export type NoteRecord = NoteItemRecord | {
|
|
50
|
+
$type: "game.flow.note.vault";
|
|
51
|
+
header: NoteVaultHeader;
|
|
52
|
+
};
|
|
53
|
+
export type NoteOperation = {
|
|
54
|
+
method: "head";
|
|
55
|
+
} | {
|
|
56
|
+
method: "list";
|
|
57
|
+
collection: NoteCollection;
|
|
58
|
+
cursor?: string;
|
|
59
|
+
} | {
|
|
60
|
+
method: "read";
|
|
61
|
+
collection: NoteCollection;
|
|
62
|
+
rkey: string;
|
|
63
|
+
} | {
|
|
64
|
+
method: "put";
|
|
65
|
+
collection: NoteCollection;
|
|
66
|
+
rkey: string;
|
|
67
|
+
record: NoteRecord;
|
|
68
|
+
swapRecord: string | null;
|
|
69
|
+
} | {
|
|
70
|
+
method: "delete";
|
|
71
|
+
collection: NoteCollection;
|
|
72
|
+
rkey: string;
|
|
73
|
+
swapRecord: string;
|
|
74
|
+
} | {
|
|
75
|
+
method: "batch";
|
|
76
|
+
swapCommit: string;
|
|
77
|
+
writes: ({
|
|
78
|
+
action: "create" | "update";
|
|
79
|
+
collection: NoteCollection;
|
|
80
|
+
rkey: string;
|
|
81
|
+
record: NoteRecord;
|
|
82
|
+
} | {
|
|
83
|
+
action: "delete";
|
|
84
|
+
collection: NoteCollection;
|
|
85
|
+
rkey: string;
|
|
86
|
+
})[];
|
|
87
|
+
};
|
|
88
|
+
export type NoteTransportDeps = {
|
|
89
|
+
enabled: boolean;
|
|
90
|
+
originAllowed: (origin: string) => boolean;
|
|
91
|
+
resolveCaller: (context: Context) => Promise<Caller | null>;
|
|
92
|
+
admit: (userId: string) => Promise<boolean>;
|
|
93
|
+
readMapping: (userId: string) => Promise<AtprotoMapping>;
|
|
94
|
+
resolve: (mapping: AtprotoMapping, signal: AbortSignal) => Promise<AtprotoResolution>;
|
|
95
|
+
session: (resolution: AtprotoResolution) => Promise<{
|
|
96
|
+
info: () => Promise<{
|
|
97
|
+
sub: string;
|
|
98
|
+
aud: string;
|
|
99
|
+
scope: string;
|
|
100
|
+
}>;
|
|
101
|
+
fetch: (path: string, init: RequestInit) => Promise<Response>;
|
|
102
|
+
}>;
|
|
103
|
+
};
|
|
104
|
+
export type NoteStoredRecord = {
|
|
105
|
+
uri: string;
|
|
106
|
+
cid: string;
|
|
107
|
+
value: NoteRecord;
|
|
108
|
+
};
|
|
109
|
+
export type NoteResponses = {
|
|
110
|
+
head: {
|
|
111
|
+
cid: string;
|
|
112
|
+
rev: string;
|
|
113
|
+
};
|
|
114
|
+
read: NoteStoredRecord;
|
|
115
|
+
list: {
|
|
116
|
+
records: NoteStoredRecord[];
|
|
117
|
+
cursor?: string;
|
|
118
|
+
};
|
|
119
|
+
put: {
|
|
120
|
+
uri: string;
|
|
121
|
+
cid: string;
|
|
122
|
+
};
|
|
123
|
+
delete: {
|
|
124
|
+
commit?: {
|
|
125
|
+
cid: string;
|
|
126
|
+
rev: string;
|
|
127
|
+
};
|
|
128
|
+
};
|
|
129
|
+
batch: {
|
|
130
|
+
commit: {
|
|
131
|
+
cid: string;
|
|
132
|
+
rev: string;
|
|
133
|
+
};
|
|
134
|
+
results: {
|
|
135
|
+
$type: string;
|
|
136
|
+
uri?: string;
|
|
137
|
+
cid?: string;
|
|
138
|
+
}[];
|
|
139
|
+
};
|
|
140
|
+
};
|
|
File without changes
|
package/dist/sdk/types/sdk.d.ts
CHANGED
|
@@ -450,3 +450,8 @@ export type FlowProfileButtonProps = ProfileButtonProps & {
|
|
|
450
450
|
flow: Flow;
|
|
451
451
|
};
|
|
452
452
|
export type ProfileMenuMountOptions = Omit<FlowProfileButtonProps, "className">;
|
|
453
|
+
export type PasskeyPrfOptions = {
|
|
454
|
+
rpId: string;
|
|
455
|
+
input: Uint8Array<ArrayBuffer>;
|
|
456
|
+
signal?: AbortSignal;
|
|
457
|
+
};
|