@freqhole/haruspex 0.0.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.
Files changed (250) hide show
  1. package/dist/flows/add-peer/machine.d.ts +36 -0
  2. package/dist/flows/add-peer/machine.d.ts.map +1 -0
  3. package/dist/flows/add-peer/machine.js +500 -0
  4. package/dist/flows/add-peer/machine.test.d.ts +2 -0
  5. package/dist/flows/add-peer/machine.test.d.ts.map +1 -0
  6. package/dist/flows/add-peer/machine.test.js +421 -0
  7. package/dist/flows/add-peer/runner.d.ts +16 -0
  8. package/dist/flows/add-peer/runner.d.ts.map +1 -0
  9. package/dist/flows/add-peer/runner.js +349 -0
  10. package/dist/flows/add-peer/runner.test.d.ts +2 -0
  11. package/dist/flows/add-peer/runner.test.d.ts.map +1 -0
  12. package/dist/flows/add-peer/runner.test.js +205 -0
  13. package/dist/flows/add-peer/types.d.ts +271 -0
  14. package/dist/flows/add-peer/types.d.ts.map +1 -0
  15. package/dist/flows/add-peer/types.js +10 -0
  16. package/dist/flows/index.d.ts +6 -0
  17. package/dist/flows/index.d.ts.map +1 -0
  18. package/dist/flows/index.js +6 -0
  19. package/dist/identity/idbStore.d.ts +51 -0
  20. package/dist/identity/idbStore.d.ts.map +1 -0
  21. package/dist/identity/idbStore.js +183 -0
  22. package/dist/identity/idbStore.test.d.ts +2 -0
  23. package/dist/identity/idbStore.test.d.ts.map +1 -0
  24. package/dist/identity/idbStore.test.js +103 -0
  25. package/dist/identity/index.d.ts +8 -0
  26. package/dist/identity/index.d.ts.map +1 -0
  27. package/dist/identity/index.js +3 -0
  28. package/dist/identity/resolve.d.ts +31 -0
  29. package/dist/identity/resolve.d.ts.map +1 -0
  30. package/dist/identity/resolve.js +37 -0
  31. package/dist/identity/resolve.test.d.ts +2 -0
  32. package/dist/identity/resolve.test.d.ts.map +1 -0
  33. package/dist/identity/resolve.test.js +105 -0
  34. package/dist/identity/types.d.ts +21 -0
  35. package/dist/identity/types.d.ts.map +1 -0
  36. package/dist/identity/types.js +1 -0
  37. package/dist/identity/webLocks.d.ts +22 -0
  38. package/dist/identity/webLocks.d.ts.map +1 -0
  39. package/dist/identity/webLocks.js +67 -0
  40. package/dist/identity/webLocks.test.d.ts +2 -0
  41. package/dist/identity/webLocks.test.d.ts.map +1 -0
  42. package/dist/identity/webLocks.test.js +125 -0
  43. package/dist/index.d.ts +2 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +1 -0
  46. package/dist/index.test.d.ts +2 -0
  47. package/dist/index.test.d.ts.map +1 -0
  48. package/dist/index.test.js +7 -0
  49. package/dist/knock/index.d.ts +10 -0
  50. package/dist/knock/index.d.ts.map +1 -0
  51. package/dist/knock/index.js +5 -0
  52. package/dist/knock/pending-checker.d.ts +19 -0
  53. package/dist/knock/pending-checker.d.ts.map +1 -0
  54. package/dist/knock/pending-checker.js +27 -0
  55. package/dist/knock/pending-checker.test.d.ts +2 -0
  56. package/dist/knock/pending-checker.test.d.ts.map +1 -0
  57. package/dist/knock/pending-checker.test.js +93 -0
  58. package/dist/knock/requester.d.ts +26 -0
  59. package/dist/knock/requester.d.ts.map +1 -0
  60. package/dist/knock/requester.js +72 -0
  61. package/dist/knock/requester.test.d.ts +2 -0
  62. package/dist/knock/requester.test.d.ts.map +1 -0
  63. package/dist/knock/requester.test.js +108 -0
  64. package/dist/knock/responder.d.ts +13 -0
  65. package/dist/knock/responder.d.ts.map +1 -0
  66. package/dist/knock/responder.js +40 -0
  67. package/dist/knock/responder.test.d.ts +2 -0
  68. package/dist/knock/responder.test.d.ts.map +1 -0
  69. package/dist/knock/responder.test.js +89 -0
  70. package/dist/knock/store.d.ts +11 -0
  71. package/dist/knock/store.d.ts.map +1 -0
  72. package/dist/knock/store.js +211 -0
  73. package/dist/knock/store.test.d.ts +2 -0
  74. package/dist/knock/store.test.d.ts.map +1 -0
  75. package/dist/knock/store.test.js +195 -0
  76. package/dist/knock/types.d.ts +144 -0
  77. package/dist/knock/types.d.ts.map +1 -0
  78. package/dist/knock/types.js +26 -0
  79. package/dist/permissions/access.d.ts +54 -0
  80. package/dist/permissions/access.d.ts.map +1 -0
  81. package/dist/permissions/access.js +56 -0
  82. package/dist/permissions/access.test.d.ts +2 -0
  83. package/dist/permissions/access.test.d.ts.map +1 -0
  84. package/dist/permissions/access.test.js +72 -0
  85. package/dist/permissions/index.d.ts +5 -0
  86. package/dist/permissions/index.d.ts.map +1 -0
  87. package/dist/permissions/index.js +2 -0
  88. package/dist/permissions/role-table.d.ts +11 -0
  89. package/dist/permissions/role-table.d.ts.map +1 -0
  90. package/dist/permissions/role-table.js +16 -0
  91. package/dist/protocol/client.d.ts +67 -0
  92. package/dist/protocol/client.d.ts.map +1 -0
  93. package/dist/protocol/client.js +195 -0
  94. package/dist/protocol/client.test.d.ts +2 -0
  95. package/dist/protocol/client.test.d.ts.map +1 -0
  96. package/dist/protocol/client.test.js +282 -0
  97. package/dist/protocol/codec.d.ts +45 -0
  98. package/dist/protocol/codec.d.ts.map +1 -0
  99. package/dist/protocol/codec.js +111 -0
  100. package/dist/protocol/codec.test.d.ts +2 -0
  101. package/dist/protocol/codec.test.d.ts.map +1 -0
  102. package/dist/protocol/codec.test.js +93 -0
  103. package/dist/protocol/extensions.d.ts +33 -0
  104. package/dist/protocol/extensions.d.ts.map +1 -0
  105. package/dist/protocol/extensions.js +36 -0
  106. package/dist/protocol/extensions.test.d.ts +2 -0
  107. package/dist/protocol/extensions.test.d.ts.map +1 -0
  108. package/dist/protocol/extensions.test.js +65 -0
  109. package/dist/protocol/fixtures.test.d.ts +2 -0
  110. package/dist/protocol/fixtures.test.d.ts.map +1 -0
  111. package/dist/protocol/fixtures.test.js +51 -0
  112. package/dist/protocol/index.d.ts +9 -0
  113. package/dist/protocol/index.d.ts.map +1 -0
  114. package/dist/protocol/index.js +4 -0
  115. package/dist/protocol/messages.d.ts +480 -0
  116. package/dist/protocol/messages.d.ts.map +1 -0
  117. package/dist/protocol/messages.js +255 -0
  118. package/dist/protocol/messages.test.d.ts +2 -0
  119. package/dist/protocol/messages.test.d.ts.map +1 -0
  120. package/dist/protocol/messages.test.js +75 -0
  121. package/dist/share/codec.d.ts +58 -0
  122. package/dist/share/codec.d.ts.map +1 -0
  123. package/dist/share/codec.js +222 -0
  124. package/dist/share/codec.test.d.ts +2 -0
  125. package/dist/share/codec.test.d.ts.map +1 -0
  126. package/dist/share/codec.test.js +150 -0
  127. package/dist/share/detect.d.ts +24 -0
  128. package/dist/share/detect.d.ts.map +1 -0
  129. package/dist/share/detect.js +25 -0
  130. package/dist/share/detect.test.d.ts +2 -0
  131. package/dist/share/detect.test.d.ts.map +1 -0
  132. package/dist/share/detect.test.js +31 -0
  133. package/dist/share/index.d.ts +7 -0
  134. package/dist/share/index.d.ts.map +1 -0
  135. package/dist/share/index.js +3 -0
  136. package/dist/share/peer-addr.d.ts +32 -0
  137. package/dist/share/peer-addr.d.ts.map +1 -0
  138. package/dist/share/peer-addr.js +72 -0
  139. package/dist/share/peer-addr.test.d.ts +2 -0
  140. package/dist/share/peer-addr.test.d.ts.map +1 -0
  141. package/dist/share/peer-addr.test.js +58 -0
  142. package/dist/solid/auth-form.d.ts +43 -0
  143. package/dist/solid/auth-form.d.ts.map +1 -0
  144. package/dist/solid/auth-form.js +55 -0
  145. package/dist/solid/auth-form.test.d.ts +2 -0
  146. package/dist/solid/auth-form.test.d.ts.map +1 -0
  147. package/dist/solid/auth-form.test.js +131 -0
  148. package/dist/solid/auth-status.d.ts +21 -0
  149. package/dist/solid/auth-status.d.ts.map +1 -0
  150. package/dist/solid/auth-status.js +58 -0
  151. package/dist/solid/auth-status.test.d.ts +2 -0
  152. package/dist/solid/auth-status.test.d.ts.map +1 -0
  153. package/dist/solid/auth-status.test.js +60 -0
  154. package/dist/solid/index.d.ts +5 -0
  155. package/dist/solid/index.d.ts.map +1 -0
  156. package/dist/solid/index.js +10 -0
  157. package/dist/solid/knock-inbox.d.ts +61 -0
  158. package/dist/solid/knock-inbox.d.ts.map +1 -0
  159. package/dist/solid/knock-inbox.js +123 -0
  160. package/dist/solid/knock-inbox.test.d.ts +2 -0
  161. package/dist/solid/knock-inbox.test.d.ts.map +1 -0
  162. package/dist/solid/knock-inbox.test.js +153 -0
  163. package/dist/solid/reauth-flow.d.ts +26 -0
  164. package/dist/solid/reauth-flow.d.ts.map +1 -0
  165. package/dist/solid/reauth-flow.js +34 -0
  166. package/dist/solid/reauth-flow.test.d.ts +2 -0
  167. package/dist/solid/reauth-flow.test.d.ts.map +1 -0
  168. package/dist/solid/reauth-flow.test.js +91 -0
  169. package/dist/state/endpoint-control.d.ts +22 -0
  170. package/dist/state/endpoint-control.d.ts.map +1 -0
  171. package/dist/state/endpoint-control.js +34 -0
  172. package/dist/state/endpoint-control.test.d.ts +2 -0
  173. package/dist/state/endpoint-control.test.d.ts.map +1 -0
  174. package/dist/state/endpoint-control.test.js +63 -0
  175. package/dist/state/friend-directory.d.ts +37 -0
  176. package/dist/state/friend-directory.d.ts.map +1 -0
  177. package/dist/state/friend-directory.js +44 -0
  178. package/dist/state/friend-directory.test.d.ts +2 -0
  179. package/dist/state/friend-directory.test.d.ts.map +1 -0
  180. package/dist/state/friend-directory.test.js +63 -0
  181. package/dist/state/index.d.ts +6 -0
  182. package/dist/state/index.d.ts.map +1 -0
  183. package/dist/state/index.js +3 -0
  184. package/dist/state/peer-names.d.ts +7 -0
  185. package/dist/state/peer-names.d.ts.map +1 -0
  186. package/dist/state/peer-names.js +21 -0
  187. package/dist/state/peer-names.test.d.ts +2 -0
  188. package/dist/state/peer-names.test.d.ts.map +1 -0
  189. package/dist/state/peer-names.test.js +29 -0
  190. package/dist/testing/idb-harness.d.ts +9 -0
  191. package/dist/testing/idb-harness.d.ts.map +1 -0
  192. package/dist/testing/idb-harness.js +19 -0
  193. package/dist/testing/idb-harness.test.d.ts +2 -0
  194. package/dist/testing/idb-harness.test.d.ts.map +1 -0
  195. package/dist/testing/idb-harness.test.js +18 -0
  196. package/dist/testing/identity-fixtures.d.ts +10 -0
  197. package/dist/testing/identity-fixtures.d.ts.map +1 -0
  198. package/dist/testing/identity-fixtures.js +21 -0
  199. package/dist/testing/identity-fixtures.test.d.ts +2 -0
  200. package/dist/testing/identity-fixtures.test.d.ts.map +1 -0
  201. package/dist/testing/identity-fixtures.test.js +28 -0
  202. package/dist/testing/index.d.ts +7 -0
  203. package/dist/testing/index.d.ts.map +1 -0
  204. package/dist/testing/index.js +11 -0
  205. package/dist/testing/knock-fixtures.d.ts +13 -0
  206. package/dist/testing/knock-fixtures.d.ts.map +1 -0
  207. package/dist/testing/knock-fixtures.js +45 -0
  208. package/dist/testing/knock-fixtures.test.d.ts +2 -0
  209. package/dist/testing/knock-fixtures.test.d.ts.map +1 -0
  210. package/dist/testing/knock-fixtures.test.js +65 -0
  211. package/dist/testing/protocol-fixtures.d.ts +7 -0
  212. package/dist/testing/protocol-fixtures.d.ts.map +1 -0
  213. package/dist/testing/protocol-fixtures.js +28 -0
  214. package/dist/testing/protocol-fixtures.test.d.ts +2 -0
  215. package/dist/testing/protocol-fixtures.test.d.ts.map +1 -0
  216. package/dist/testing/protocol-fixtures.test.js +19 -0
  217. package/dist/testing/state-fixtures.d.ts +33 -0
  218. package/dist/testing/state-fixtures.d.ts.map +1 -0
  219. package/dist/testing/state-fixtures.js +67 -0
  220. package/dist/testing/state-fixtures.test.d.ts +2 -0
  221. package/dist/testing/state-fixtures.test.d.ts.map +1 -0
  222. package/dist/testing/state-fixtures.test.js +68 -0
  223. package/dist/testing/webauthn-mocks.d.ts +27 -0
  224. package/dist/testing/webauthn-mocks.d.ts.map +1 -0
  225. package/dist/testing/webauthn-mocks.js +78 -0
  226. package/dist/testing/webauthn-mocks.test.d.ts +2 -0
  227. package/dist/testing/webauthn-mocks.test.d.ts.map +1 -0
  228. package/dist/testing/webauthn-mocks.test.js +40 -0
  229. package/dist/webauthn/ceremony.d.ts +76 -0
  230. package/dist/webauthn/ceremony.d.ts.map +1 -0
  231. package/dist/webauthn/ceremony.js +136 -0
  232. package/dist/webauthn/ceremony.test.d.ts +2 -0
  233. package/dist/webauthn/ceremony.test.d.ts.map +1 -0
  234. package/dist/webauthn/ceremony.test.js +245 -0
  235. package/dist/webauthn/codec.d.ts +39 -0
  236. package/dist/webauthn/codec.d.ts.map +1 -0
  237. package/dist/webauthn/codec.js +118 -0
  238. package/dist/webauthn/codec.test.d.ts +2 -0
  239. package/dist/webauthn/codec.test.d.ts.map +1 -0
  240. package/dist/webauthn/codec.test.js +126 -0
  241. package/dist/webauthn/index.d.ts +7 -0
  242. package/dist/webauthn/index.d.ts.map +1 -0
  243. package/dist/webauthn/index.js +3 -0
  244. package/dist/webauthn/transport.d.ts +58 -0
  245. package/dist/webauthn/transport.d.ts.map +1 -0
  246. package/dist/webauthn/transport.js +6 -0
  247. package/dist/webauthn/types.d.ts +78 -0
  248. package/dist/webauthn/types.d.ts.map +1 -0
  249. package/dist/webauthn/types.js +29 -0
  250. package/package.json +83 -0
@@ -0,0 +1,126 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { arrayBufferToBase64, base64ToUint8Array, isWebAuthnAvailable, prepareAuthenticationOptions, prepareRegistrationOptions, serializeAuthenticationCredential, serializeRegistrationCredential, uint8ArrayToBase64, } from "./codec.js";
3
+ describe("base64url round-trip", () => {
4
+ it("round-trips arbitrary bytes, including values that need + / and padding", () => {
5
+ const bytes = new Uint8Array([0, 1, 2, 62, 63, 64, 251, 252, 253, 254, 255]);
6
+ const encoded = uint8ArrayToBase64(bytes);
7
+ expect(encoded).not.toMatch(/[+/=]/);
8
+ expect(base64ToUint8Array(encoded)).toEqual(bytes);
9
+ });
10
+ it("arrayBufferToBase64 matches uint8ArrayToBase64 for the same bytes", () => {
11
+ const bytes = new Uint8Array([10, 20, 30]);
12
+ expect(arrayBufferToBase64(bytes.buffer)).toBe(uint8ArrayToBase64(bytes));
13
+ });
14
+ });
15
+ describe("prepareRegistrationOptions", () => {
16
+ it("converts base64url challenge/user-id/excludeCredentials to raw bytes", () => {
17
+ const challengeBytes = new Uint8Array([1, 2, 3]);
18
+ const userIdBytes = new Uint8Array([9, 9]);
19
+ const excludeIdBytes = new Uint8Array([5]);
20
+ const challenge = {
21
+ publicKey: {
22
+ rp: { name: "freqhole" },
23
+ user: {
24
+ id: uint8ArrayToBase64(userIdBytes),
25
+ name: "alice",
26
+ displayName: "Alice",
27
+ },
28
+ challenge: uint8ArrayToBase64(challengeBytes),
29
+ pubKeyCredParams: [{ type: "public-key", alg: -7 }],
30
+ excludeCredentials: [
31
+ { id: uint8ArrayToBase64(excludeIdBytes), type: "public-key" },
32
+ ],
33
+ },
34
+ };
35
+ const options = prepareRegistrationOptions(challenge);
36
+ const publicKey = options.publicKey;
37
+ expect(publicKey.challenge).toEqual(challengeBytes);
38
+ expect(publicKey.user.id).toEqual(userIdBytes);
39
+ expect(publicKey.excludeCredentials[0].id).toEqual(excludeIdBytes);
40
+ expect(publicKey.rp).toEqual({ name: "freqhole" });
41
+ });
42
+ it("omits excludeCredentials when the server did not send any", () => {
43
+ const challenge = {
44
+ publicKey: {
45
+ rp: { name: "freqhole" },
46
+ user: { id: "AA", name: "alice", displayName: "Alice" },
47
+ challenge: "AQ",
48
+ pubKeyCredParams: [{ type: "public-key", alg: -7 }],
49
+ },
50
+ };
51
+ const options = prepareRegistrationOptions(challenge);
52
+ expect(options.publicKey.excludeCredentials).toBeUndefined();
53
+ });
54
+ });
55
+ describe("prepareAuthenticationOptions", () => {
56
+ it("converts base64url challenge/allowCredentials to raw bytes", () => {
57
+ const challengeBytes = new Uint8Array([4, 5, 6]);
58
+ const allowIdBytes = new Uint8Array([7]);
59
+ const challenge = {
60
+ publicKey: {
61
+ challenge: uint8ArrayToBase64(challengeBytes),
62
+ allowCredentials: [
63
+ { id: uint8ArrayToBase64(allowIdBytes), type: "public-key" },
64
+ ],
65
+ },
66
+ };
67
+ const options = prepareAuthenticationOptions(challenge);
68
+ const publicKey = options.publicKey;
69
+ expect(publicKey.challenge).toEqual(challengeBytes);
70
+ expect(publicKey.allowCredentials[0].id).toEqual(allowIdBytes);
71
+ });
72
+ });
73
+ /** builds a fake PublicKeyCredential-shaped object for registration; only
74
+ * the fields serializeRegistrationCredential reads are present. */
75
+ function fakeRegistrationCredential() {
76
+ return {
77
+ id: "cred-id",
78
+ rawId: new Uint8Array([1, 2, 3]).buffer,
79
+ response: {
80
+ attestationObject: new Uint8Array([4, 5]).buffer,
81
+ clientDataJSON: new Uint8Array([6, 7]).buffer,
82
+ },
83
+ };
84
+ }
85
+ /** builds a fake PublicKeyCredential-shaped object for authentication. */
86
+ function fakeAuthenticationCredential(withUserHandle) {
87
+ return {
88
+ id: "cred-id",
89
+ rawId: new Uint8Array([1, 2, 3]).buffer,
90
+ response: {
91
+ authenticatorData: new Uint8Array([8]).buffer,
92
+ clientDataJSON: new Uint8Array([9]).buffer,
93
+ signature: new Uint8Array([10]).buffer,
94
+ userHandle: withUserHandle ? new Uint8Array([11]).buffer : null,
95
+ },
96
+ };
97
+ }
98
+ describe("serializeRegistrationCredential", () => {
99
+ it("serializes a credential into the server wire format", () => {
100
+ const serialized = serializeRegistrationCredential(fakeRegistrationCredential());
101
+ expect(serialized).toEqual({
102
+ id: "cred-id",
103
+ rawId: uint8ArrayToBase64(new Uint8Array([1, 2, 3])),
104
+ type: "public-key",
105
+ response: {
106
+ attestationObject: uint8ArrayToBase64(new Uint8Array([4, 5])),
107
+ clientDataJSON: uint8ArrayToBase64(new Uint8Array([6, 7])),
108
+ },
109
+ });
110
+ });
111
+ });
112
+ describe("serializeAuthenticationCredential", () => {
113
+ it("serializes a credential with a user handle", () => {
114
+ const serialized = serializeAuthenticationCredential(fakeAuthenticationCredential(true));
115
+ expect(serialized.response.userHandle).toBe(uint8ArrayToBase64(new Uint8Array([11])));
116
+ });
117
+ it("omits userHandle when the authenticator did not send one (discoverable flow)", () => {
118
+ const serialized = serializeAuthenticationCredential(fakeAuthenticationCredential(false));
119
+ expect(serialized.response.userHandle).toBeUndefined();
120
+ });
121
+ });
122
+ describe("isWebAuthnAvailable", () => {
123
+ it("is false when navigator is absent (node/vitest environment)", () => {
124
+ expect(isWebAuthnAvailable()).toBe(false);
125
+ });
126
+ });
@@ -0,0 +1,7 @@
1
+ export type { RegisterPublicKeyCredential, AuthenticationPublicKeyCredential, ServerCredentialDescriptor, RegistrationChallenge, AuthenticationChallenge, } from "./types.js";
2
+ export { AuthenticatorAttestationResponseSchema, RegisterPublicKeyCredentialSchema, AuthenticatorAssertionResponseSchema, AuthenticationPublicKeyCredentialSchema, } from "./types.js";
3
+ export { arrayBufferToBase64, base64ToUint8Array, isWebAuthnAvailable, prepareAuthenticationOptions, prepareRegistrationOptions, serializeAuthenticationCredential, serializeRegistrationCredential, uint8ArrayToBase64, } from "./codec.js";
4
+ export type { AuthOutcome, ChallengeResponse, FinishRequest, LoginStartRequest, RegisterStartRequest, TransportFailure, TransportResult, TransportSuccess, WebauthnTransport, WhoamiOutcome, } from "./transport.js";
5
+ export type { AuthenticateArgs, CeremonyFailure, CeremonyResult, CreateCredentialFn, GetCredentialFn, LoginPasskeyArgs, PasskeyCeremonyDeps, RegisterPasskeyArgs, } from "./ceremony.js";
6
+ export { authenticate, loginWithPasskey, registerWithPasskey, whoami, } from "./ceremony.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/webauthn/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,2BAA2B,EAC3B,iCAAiC,EACjC,0BAA0B,EAC1B,qBAAqB,EACrB,uBAAuB,GACxB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,sCAAsC,EACtC,iCAAiC,EACjC,oCAAoC,EACpC,uCAAuC,GACxC,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,4BAA4B,EAC5B,0BAA0B,EAC1B,iCAAiC,EACjC,+BAA+B,EAC/B,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAEpB,YAAY,EACV,WAAW,EACX,iBAAiB,EACjB,aAAa,EACb,iBAAiB,EACjB,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,GACd,MAAM,gBAAgB,CAAC;AAExB,YAAY,EACV,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,MAAM,GACP,MAAM,eAAe,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { AuthenticatorAttestationResponseSchema, RegisterPublicKeyCredentialSchema, AuthenticatorAssertionResponseSchema, AuthenticationPublicKeyCredentialSchema, } from "./types.js";
2
+ export { arrayBufferToBase64, base64ToUint8Array, isWebAuthnAvailable, prepareAuthenticationOptions, prepareRegistrationOptions, serializeAuthenticationCredential, serializeRegistrationCredential, uint8ArrayToBase64, } from "./codec.js";
3
+ export { authenticate, loginWithPasskey, registerWithPasskey, whoami, } from "./ceremony.js";
@@ -0,0 +1,58 @@
1
+ import type { AuthenticationChallenge, AuthenticationPublicKeyCredential, RegisterPublicKeyCredential, RegistrationChallenge } from "./types.js";
2
+ export interface TransportSuccess<T> {
3
+ success: true;
4
+ data: T;
5
+ }
6
+ export interface TransportFailure {
7
+ success: false;
8
+ error: string;
9
+ }
10
+ export type TransportResult<T> = TransportSuccess<T> | TransportFailure;
11
+ export interface RegisterStartRequest {
12
+ username: string;
13
+ /** the caller's origin, forwarded so the server can derive its rp id. */
14
+ origin: string;
15
+ /** required unless the caller already has an authenticated device link
16
+ * to the target identity (adding a second passkey via node-based auth). */
17
+ inviteCode?: string;
18
+ }
19
+ export interface LoginStartRequest {
20
+ /** omit for the discoverable-credential flow (authenticator picks). */
21
+ username?: string;
22
+ origin: string;
23
+ }
24
+ /**
25
+ * a start call's response: the challenge to feed the browser, plus a round
26
+ * -trip token identifying it server-side. `nonce` is present for a p2p
27
+ * remote and absent for an http remote, which instead carries the
28
+ * challenge state in a session cookie.
29
+ */
30
+ export interface ChallengeResponse<TChallenge> {
31
+ nonce?: string;
32
+ challenge: TChallenge;
33
+ }
34
+ export interface FinishRequest<TCredential> {
35
+ nonce?: string;
36
+ origin: string;
37
+ credential: TCredential;
38
+ }
39
+ export interface AuthOutcome {
40
+ userId?: string;
41
+ username?: string;
42
+ role?: string;
43
+ }
44
+ export interface WhoamiOutcome {
45
+ authenticated: boolean;
46
+ userId?: string;
47
+ username?: string;
48
+ role?: string;
49
+ }
50
+ /** the four ceremony calls plus a caller-identity check, bound to one remote. */
51
+ export interface WebauthnTransport {
52
+ registerStart(req: RegisterStartRequest): Promise<TransportResult<ChallengeResponse<RegistrationChallenge>>>;
53
+ registerFinish(req: FinishRequest<RegisterPublicKeyCredential>): Promise<TransportResult<AuthOutcome>>;
54
+ loginStart(req: LoginStartRequest): Promise<TransportResult<ChallengeResponse<AuthenticationChallenge>>>;
55
+ loginFinish(req: FinishRequest<AuthenticationPublicKeyCredential>): Promise<TransportResult<AuthOutcome>>;
56
+ whoami(): Promise<WhoamiOutcome>;
57
+ }
58
+ //# sourceMappingURL=transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/webauthn/transport.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,uBAAuB,EACvB,iCAAiC,EACjC,2BAA2B,EAC3B,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,EAAE,CAAC,CAAC;CACT;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,gBAAgB,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC;AAExE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;IACf;gFAC4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB,CAAC,UAAU;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,UAAU,CAAC;CACvB;AAED,MAAM,WAAW,aAAa,CAAC,WAAW;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,WAAW,CAAC;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,iFAAiF;AACjF,MAAM,WAAW,iBAAiB;IAChC,aAAa,CACX,GAAG,EAAE,oBAAoB,GACxB,OAAO,CAAC,eAAe,CAAC,iBAAiB,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACtE,cAAc,CACZ,GAAG,EAAE,aAAa,CAAC,2BAA2B,CAAC,GAC9C,OAAO,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC;IACzC,UAAU,CACR,GAAG,EAAE,iBAAiB,GACrB,OAAO,CAAC,eAAe,CAAC,iBAAiB,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC;IACxE,WAAW,CACT,GAAG,EAAE,aAAa,CAAC,iCAAiC,CAAC,GACpD,OAAO,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC;IACzC,MAAM,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC;CAClC"}
@@ -0,0 +1,6 @@
1
+ // the transport surface a webauthn ceremony runs against - an injected
2
+ // dependency so the same ceremony logic serves an http remote (ceremony
3
+ // state carried in a session cookie) and a p2p remote (ceremony state
4
+ // threaded through an explicit nonce) alike. concrete transports (http
5
+ // fetch, p2p client bindings) live with the consuming app.
6
+ export {};
@@ -0,0 +1,78 @@
1
+ import { z } from "zod";
2
+ export declare const AuthenticatorAttestationResponseSchema: z.ZodObject<{
3
+ attestationObject: z.ZodString;
4
+ clientDataJSON: z.ZodString;
5
+ }, z.core.$strip>;
6
+ export declare const RegisterPublicKeyCredentialSchema: z.ZodObject<{
7
+ id: z.ZodString;
8
+ rawId: z.ZodString;
9
+ type: z.ZodLiteral<"public-key">;
10
+ response: z.ZodObject<{
11
+ attestationObject: z.ZodString;
12
+ clientDataJSON: z.ZodString;
13
+ }, z.core.$strip>;
14
+ }, z.core.$strip>;
15
+ export declare const AuthenticatorAssertionResponseSchema: z.ZodObject<{
16
+ authenticatorData: z.ZodString;
17
+ clientDataJSON: z.ZodString;
18
+ signature: z.ZodString;
19
+ userHandle: z.ZodOptional<z.ZodString>;
20
+ }, z.core.$strip>;
21
+ export declare const AuthenticationPublicKeyCredentialSchema: z.ZodObject<{
22
+ id: z.ZodString;
23
+ rawId: z.ZodString;
24
+ type: z.ZodLiteral<"public-key">;
25
+ response: z.ZodObject<{
26
+ authenticatorData: z.ZodString;
27
+ clientDataJSON: z.ZodString;
28
+ signature: z.ZodString;
29
+ userHandle: z.ZodOptional<z.ZodString>;
30
+ }, z.core.$strip>;
31
+ }, z.core.$strip>;
32
+ export type RegisterPublicKeyCredential = z.infer<typeof RegisterPublicKeyCredentialSchema>;
33
+ export type AuthenticationPublicKeyCredential = z.infer<typeof AuthenticationPublicKeyCredentialSchema>;
34
+ /** a base64url-encoded credential descriptor, as sent by the server. */
35
+ export interface ServerCredentialDescriptor {
36
+ id: string;
37
+ type: "public-key";
38
+ transports?: AuthenticatorTransport[];
39
+ }
40
+ /**
41
+ * the server's registration challenge, ready to feed into
42
+ * `prepareRegistrationOptions`. base64url fields (challenge, user.id,
43
+ * excludeCredentials[].id) are still strings at this point - the browser
44
+ * needs raw bytes, which prepareRegistrationOptions converts.
45
+ */
46
+ export interface RegistrationChallenge {
47
+ publicKey: {
48
+ rp: {
49
+ id?: string;
50
+ name: string;
51
+ };
52
+ user: {
53
+ id: string;
54
+ name: string;
55
+ displayName: string;
56
+ };
57
+ challenge: string;
58
+ pubKeyCredParams: PublicKeyCredentialParameters[];
59
+ timeout?: number;
60
+ excludeCredentials?: ServerCredentialDescriptor[];
61
+ authenticatorSelection?: AuthenticatorSelectionCriteria;
62
+ attestation?: AttestationConveyancePreference;
63
+ };
64
+ }
65
+ /**
66
+ * the server's authentication challenge, ready to feed into
67
+ * `prepareAuthenticationOptions`.
68
+ */
69
+ export interface AuthenticationChallenge {
70
+ publicKey: {
71
+ challenge: string;
72
+ timeout?: number;
73
+ rpId?: string;
74
+ allowCredentials?: ServerCredentialDescriptor[];
75
+ userVerification?: UserVerificationRequirement;
76
+ };
77
+ }
78
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/webauthn/types.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,sCAAsC;;;iBAGjD,CAAC;AAEH,eAAO,MAAM,iCAAiC;;;;;;;;iBAK5C,CAAC;AAEH,eAAO,MAAM,oCAAoC;;;;;iBAK/C,CAAC;AAEH,eAAO,MAAM,uCAAuC;;;;;;;;;;iBAKlD,CAAC;AAEH,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAC/C,OAAO,iCAAiC,CACzC,CAAC;AACF,MAAM,MAAM,iCAAiC,GAAG,CAAC,CAAC,KAAK,CACrD,OAAO,uCAAuC,CAC/C,CAAC;AAEF,wEAAwE;AACxE,MAAM,WAAW,0BAA0B;IACzC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,YAAY,CAAC;IACnB,UAAU,CAAC,EAAE,sBAAsB,EAAE,CAAC;CACvC;AAED;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE;QACT,EAAE,EAAE;YAAE,EAAE,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC;QAClC,IAAI,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAC;YAAC,WAAW,EAAE,MAAM,CAAA;SAAE,CAAC;QACxD,SAAS,EAAE,MAAM,CAAC;QAClB,gBAAgB,EAAE,6BAA6B,EAAE,CAAC;QAClD,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,kBAAkB,CAAC,EAAE,0BAA0B,EAAE,CAAC;QAClD,sBAAsB,CAAC,EAAE,8BAA8B,CAAC;QACxD,WAAW,CAAC,EAAE,+BAA+B,CAAC;KAC/C,CAAC;CACH;AAED;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE;QACT,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,gBAAgB,CAAC,EAAE,0BAA0B,EAAE,CAAC;QAChD,gBAAgB,CAAC,EAAE,2BAA2B,CAAC;KAChD,CAAC;CACH"}
@@ -0,0 +1,29 @@
1
+ // wire shapes for the webauthn passkey ceremony: the credential blobs the
2
+ // browser hands back from navigator.credentials.create()/get() (serialized
3
+ // to base64url strings for transport), and the server's challenge shapes fed
4
+ // into those calls. field names are camelCase, matching the friendz
5
+ // protocol's wire convention and the shapes webauthn-rs (the rust side's
6
+ // ceremony implementation) serializes.
7
+ import { z } from "zod";
8
+ export const AuthenticatorAttestationResponseSchema = z.object({
9
+ attestationObject: z.string(),
10
+ clientDataJSON: z.string(),
11
+ });
12
+ export const RegisterPublicKeyCredentialSchema = z.object({
13
+ id: z.string(),
14
+ rawId: z.string(),
15
+ type: z.literal("public-key"),
16
+ response: AuthenticatorAttestationResponseSchema,
17
+ });
18
+ export const AuthenticatorAssertionResponseSchema = z.object({
19
+ authenticatorData: z.string(),
20
+ clientDataJSON: z.string(),
21
+ signature: z.string(),
22
+ userHandle: z.string().optional(),
23
+ });
24
+ export const AuthenticationPublicKeyCredentialSchema = z.object({
25
+ id: z.string(),
26
+ rawId: z.string(),
27
+ type: z.literal("public-key"),
28
+ response: AuthenticatorAssertionResponseSchema,
29
+ });
package/package.json ADDED
@@ -0,0 +1,83 @@
1
+ {
2
+ "name": "@freqhole/haruspex",
3
+ "version": "0.0.0",
4
+ "private": false,
5
+ "type": "module",
6
+ "description": "freqhole auth domain: identity, webauthn, knock + friendz protocols, permissions",
7
+ "license": "UNLICENSED",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/freqhole/tomb"
11
+ },
12
+ "files": [
13
+ "dist"
14
+ ],
15
+ "exports": {
16
+ ".": {
17
+ "types": "./dist/index.d.ts",
18
+ "import": "./dist/index.js"
19
+ },
20
+ "./identity": {
21
+ "types": "./dist/identity/index.d.ts",
22
+ "import": "./dist/identity/index.js"
23
+ },
24
+ "./webauthn": {
25
+ "types": "./dist/webauthn/index.d.ts",
26
+ "import": "./dist/webauthn/index.js"
27
+ },
28
+ "./knock": {
29
+ "types": "./dist/knock/index.d.ts",
30
+ "import": "./dist/knock/index.js"
31
+ },
32
+ "./share": {
33
+ "types": "./dist/share/index.d.ts",
34
+ "import": "./dist/share/index.js"
35
+ },
36
+ "./flows": {
37
+ "types": "./dist/flows/index.d.ts",
38
+ "import": "./dist/flows/index.js"
39
+ },
40
+ "./permissions": {
41
+ "types": "./dist/permissions/index.d.ts",
42
+ "import": "./dist/permissions/index.js"
43
+ },
44
+ "./protocol": {
45
+ "types": "./dist/protocol/index.d.ts",
46
+ "import": "./dist/protocol/index.js"
47
+ },
48
+ "./state": {
49
+ "types": "./dist/state/index.d.ts",
50
+ "import": "./dist/state/index.js"
51
+ },
52
+ "./solid": {
53
+ "types": "./dist/solid/index.d.ts",
54
+ "import": "./dist/solid/index.js"
55
+ },
56
+ "./testing": {
57
+ "types": "./dist/testing/index.d.ts",
58
+ "import": "./dist/testing/index.js"
59
+ }
60
+ },
61
+ "scripts": {
62
+ "build": "tsc -p tsconfig.json",
63
+ "typecheck": "tsc --noEmit",
64
+ "test": "vitest run"
65
+ },
66
+ "peerDependencies": {
67
+ "solid-js": "^1.9.0",
68
+ "zod": "^4.3.5"
69
+ },
70
+ "peerDependenciesMeta": {
71
+ "solid-js": {
72
+ "optional": true
73
+ }
74
+ },
75
+ "devDependencies": {
76
+ "@types/node": "^26.1.1",
77
+ "fake-indexeddb": "^6.0.0",
78
+ "solid-js": "^1.9.0",
79
+ "typescript": "^5.6.0",
80
+ "vitest": "^2.1.0",
81
+ "zod": "^4.3.5"
82
+ }
83
+ }