@human-gateway/sdk 0.0.1 → 0.1.0-alpha.1

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/README.md CHANGED
@@ -1,21 +1,711 @@
1
1
  # Human Gateway SDK
2
2
 
3
- Official Human Gateway SDK placeholder.
3
+ Human Gateway SDK lets partners add privacy-first human verification and human authentication to their apps without handling identity, biometrics, World ID internals, nullifiers, or proof verification logic.
4
4
 
5
- This package reserves the official Human Gateway SDK namespace.
5
+ Human Gateway is designed around two identifiers:
6
6
 
7
- The production SDK is under active development and will be released in a future version.
7
+ ```txt
8
+ projectId -> identifies your Human Gateway project
9
+ actionKey -> identifies the specific verify/auth flow inside that project
10
+ ```
8
11
 
9
- ## Status
12
+ For production integrations, pass an `actionKey` explicitly.
10
13
 
11
- Placeholder release (`v0.0.1`)
14
+ ---
12
15
 
13
- ## Package
16
+ ## Installation
14
17
 
15
18
  ```bash
16
19
  npm install @human-gateway/sdk
17
20
  ```
18
21
 
19
- ## Purpose
22
+ > The SDK is currently in alpha. Package publication should be handled as a controlled release step. For local development, use the package from the Human Gateway monorepo.
23
+
24
+ ---
25
+
26
+ ## Quickstart: Verify a human
27
+
28
+ ```ts
29
+ import { HumanGateway } from "@human-gateway/sdk";
30
+
31
+ const hg = new HumanGateway({
32
+ projectId: "project_xxx",
33
+ });
34
+
35
+ const result = await hg.verify({
36
+ actionKey: "hg_verify_action_key_xxx",
37
+ });
38
+
39
+ if (result.verified_human) {
40
+ // Hide verify button
41
+ // Show verified badge
42
+ // Optionally wait for the signed backend callback before persisting state
43
+ }
44
+ ```
45
+
46
+ Example verification result:
47
+
48
+ ```json
49
+ {
50
+ "success": true,
51
+ "verified_human": true,
52
+ "verification_level": "orb",
53
+ "unique_for_partner": true,
54
+ "already_verified": false,
55
+ "project_id": "project_xxx"
56
+ }
57
+ ```
58
+
59
+ ---
60
+
61
+ ## Quickstart: Sign in a verified human
62
+
63
+ ```ts
64
+ import { HumanGateway } from "@human-gateway/sdk";
65
+
66
+ const hg = new HumanGateway({
67
+ projectId: "project_xxx",
68
+ });
69
+
70
+ const result = await hg.auth({
71
+ actionKey: "hg_auth_action_key_xxx",
72
+ });
73
+
74
+ if (result.success && result.verified_human) {
75
+ // Update your UI
76
+ // Store the returned partner-scoped session only according to your own app flow
77
+ }
78
+ ```
79
+
80
+ Example auth result:
81
+
82
+ ```json
83
+ {
84
+ "success": true,
85
+ "event": "auth.completed",
86
+ "verified_human": true,
87
+ "verification_level": "orb",
88
+ "partner_user_id": "partner_user_xxx",
89
+ "auth_session_id": "auth_session_xxx",
90
+ "project_id": "project_xxx",
91
+ "expires_at": "2026-06-25T00:00:00.000Z"
92
+ }
93
+ ```
94
+
95
+ ---
96
+
97
+ ## Project vs Action
98
+
99
+ A Human Gateway project represents one partner integration.
100
+
101
+ An action represents a specific flow inside that project.
102
+
103
+ Example:
104
+
105
+ ```txt
106
+ Project: My SaaS App
107
+
108
+ Actions:
109
+ - Verify signup
110
+ - Auth login
111
+ - Verify voting
112
+ - Auth dashboard access
113
+ ```
114
+
115
+ Use the same `projectId` for the project and pass the correct `actionKey` for the flow you want to run.
116
+
117
+ ```ts
118
+ await hg.verify({
119
+ actionKey: "hg_verify_signup_xxx",
120
+ });
121
+
122
+ await hg.auth({
123
+ actionKey: "hg_auth_login_xxx",
124
+ });
125
+ ```
126
+
127
+ If `actionKey` is omitted, Human Gateway may use a fallback active action for compatibility. Explicit `actionKey` usage is recommended for production integrations.
128
+
129
+ ---
130
+
131
+ ## What Human Gateway does
132
+
133
+ Human Gateway verifies that a real human completed a World ID proof inside a specific project/action context.
134
+
135
+ Human Gateway does **not** expose:
136
+
137
+ * personal identity
138
+ * emails
139
+ * names
140
+ * biometrics
141
+ * World ID nullifiers
142
+ * raw World ID proof data
143
+ * internal Human Gateway user records
144
+
145
+ The partner receives only scoped results needed to update product behavior.
146
+
147
+ ---
148
+
149
+ ## Frontend options
150
+
151
+ ```ts
152
+ const result = await hg.verify({
153
+ actionKey: "hg_verify_action_key_xxx",
154
+ onOpen: () => {
155
+ console.log("Verification popup opened");
156
+ },
157
+ onSuccess: (result) => {
158
+ console.log("Verification completed:", result);
159
+ },
160
+ onError: (error) => {
161
+ console.error("Verification failed:", error.code);
162
+ },
163
+ });
164
+ ```
165
+
166
+ ```ts
167
+ const result = await hg.auth({
168
+ actionKey: "hg_auth_action_key_xxx",
169
+ onOpen: () => {
170
+ console.log("Auth popup opened");
171
+ },
172
+ onSuccess: (result) => {
173
+ console.log("Auth completed:", result);
174
+ },
175
+ onError: (error) => {
176
+ console.error("Auth failed:", error.code);
177
+ },
178
+ });
179
+ ```
180
+
181
+ ---
182
+
183
+ ## SDK configuration
184
+
185
+ ```ts
186
+ const hg = new HumanGateway({
187
+ projectId: "project_xxx",
188
+ environment: "production",
189
+ mode: "auto",
190
+ timeoutMs: 300000,
191
+ });
192
+ ```
193
+
194
+ Available options:
195
+
196
+ ```ts
197
+ type HumanGatewayOptions = {
198
+ projectId: string;
199
+ environment?: "production" | "sandbox";
200
+ mode?: "auto" | "popup" | "modal" | "redirect";
201
+ baseUrl?: string;
202
+ timeoutMs?: number;
203
+ };
204
+ ```
205
+
206
+ `environment` identifies the intended Human Gateway project environment.
207
+
208
+ ```txt
209
+ production -> production project/action configuration
210
+ sandbox -> sandbox project/action configuration
211
+ ```
212
+
213
+ Both `production` and `sandbox` currently use the hosted Human Gateway domain by default:
214
+
215
+ ```txt
216
+ https://humangateway.dev
217
+ ```
218
+
219
+ For local development, pass `baseUrl` explicitly.
220
+
221
+ Alpha behavior:
222
+
223
+ * `popup` is supported.
224
+ * `auto` currently uses popup behavior.
225
+ * `modal` is planned.
226
+ * `redirect` is planned.
227
+
228
+ ---
229
+
230
+ ## Verify options
231
+
232
+ ```ts
233
+ type HumanGatewayVerifyOptions = {
234
+ actionKey?: string;
235
+ onOpen?: () => void;
236
+ onClose?: () => void;
237
+ onSuccess?: (result: HumanGatewayResult) => void;
238
+ onError?: (error: HumanGatewayError) => void;
239
+ };
240
+ ```
241
+
242
+ Verify result:
243
+
244
+ ```ts
245
+ type HumanGatewayResult = {
246
+ success: boolean;
247
+ verified_human: boolean;
248
+ verification_level: "device" | "document" | "secure_document" | "orb" | null;
249
+ unique_for_partner: boolean;
250
+ already_verified: boolean;
251
+ project_id: string;
252
+ };
253
+ ```
254
+
255
+ ---
256
+
257
+ ## Auth options
258
+
259
+ ```ts
260
+ type HumanGatewayAuthOptions = {
261
+ actionKey?: string;
262
+ onOpen?: () => void;
263
+ onClose?: () => void;
264
+ onSuccess?: (result: HumanGatewayAuthResult) => void;
265
+ onError?: (error: HumanGatewayError) => void;
266
+ };
267
+ ```
268
+
269
+ Auth result:
270
+
271
+ ```ts
272
+ type HumanGatewayAuthResult = {
273
+ success: boolean;
274
+ event?: "auth.completed";
275
+ verified_human: boolean;
276
+ verification_level: "device" | "document" | "secure_document" | "orb" | null;
277
+ partner_user_id: string;
278
+ auth_session_id: string;
279
+ project_id: string;
280
+ expires_at: string;
281
+ };
282
+ ```
283
+
284
+ ---
285
+
286
+ ## Popup behavior
287
+
288
+ The SDK opens a Human Gateway hosted flow in a centered browser popup.
289
+
290
+ This is expected behavior:
291
+
292
+ * The popup may show the browser address bar.
293
+ * The popup may be resizable or maximizable depending on the browser.
294
+ * The popup attempts to close itself after a successful flow.
295
+ * Some browsers may prevent programmatic closing; in that case, the user can close it manually.
296
+
297
+ The visible address bar is intentional and useful: it lets users confirm they are interacting with a legitimate Human Gateway domain.
298
+
299
+ ### User gesture requirement
300
+
301
+ Call `hg.verify()` or `hg.auth()` directly from a user action such as a button click.
302
+
303
+ Modern browsers may block popups if they are opened after a long asynchronous operation, delayed promise, timer, or background task. For the best success rate, start the Human Gateway flow immediately inside the user interaction handler.
304
+
305
+ Recommended:
306
+
307
+ ```ts
308
+ button.addEventListener("click", async () => {
309
+ const result = await hg.verify({
310
+ actionKey: "hg_verify_action_key_xxx",
311
+ });
312
+
313
+ console.log(result);
314
+ });
315
+ ```
316
+
317
+ Avoid delaying the popup:
318
+
319
+ ```ts
320
+ button.addEventListener("click", async () => {
321
+ await doLongAsyncWork();
322
+
323
+ const result = await hg.verify({
324
+ actionKey: "hg_verify_action_key_xxx",
325
+ });
326
+
327
+ console.log(result);
328
+ });
329
+ ```
330
+
331
+ ---
332
+
333
+ ## Allowed origin vs callback URL
334
+
335
+ Human Gateway uses two different URLs during an integration:
336
+
337
+ ```txt
338
+ Allowed origin -> frontend origin that can launch hosted Human Gateway flows
339
+ Callback URL -> backend endpoint that receives signed POST callbacks
340
+ ```
341
+
342
+ Examples:
343
+
344
+ ```txt
345
+ Allowed origin: https://yourapp.com
346
+ Callback URL: https://yourapp.com/api/hg/callback
347
+ ```
348
+
349
+ Do not configure only your domain as the callback URL:
350
+
351
+ ```txt
352
+ Incorrect callback URL: https://yourapp.com
353
+ ```
354
+
355
+ Human Gateway sends `POST` requests to the exact callback URL configured in Partner Console. The callback URL must include the full backend endpoint path. Partners can choose their own backend route, for example:
356
+
357
+ ```txt
358
+ https://yourapp.com/api/hg/callback
359
+ https://yourapp.com/api/webhooks/human-gateway
360
+ https://yourapp.com/webhooks/hg
361
+ https://yourapp.com/api/world/hg
362
+ ```
363
+
364
+ The allowed origin is used by the frontend SDK and hosted flows. The callback URL is used by Human Gateway server-to-server delivery.
365
+
366
+ ---
367
+
368
+ ## Frontend result vs backend callback
369
+
370
+ The frontend SDK result is useful for immediate UI updates.
371
+
372
+ The signed backend callback should be treated as the durable source of truth.
373
+
374
+ ```txt
375
+ Frontend result -> update UI
376
+ Signed callback -> persist verified/auth state in partner backend
377
+ ```
378
+
379
+ A malicious user can manipulate frontend state. They cannot forge a valid Human Gateway callback without the callback secret.
380
+
381
+ ---
382
+
383
+ ## Backend callback verification
384
+
385
+ Human Gateway sends signed callbacks to the partner backend.
386
+
387
+ Configure the callback URL in Partner Console as the full backend endpoint path, for example:
388
+
389
+ ```txt
390
+ https://yourapp.com/api/hg/callback
391
+ ```
392
+
393
+ Do not configure only `https://yourapp.com`; Human Gateway will send the callback to the exact URL you enter.
394
+
395
+ Server-side helpers are exported from `@human-gateway/sdk/server`.
396
+
397
+ You do not need to create a `HumanGateway` instance on your backend. The server helpers are pure functions designed to validate callback requests using the raw request body, signed headers, and your project callback secret.
398
+
399
+ Callback headers:
400
+
401
+ ```txt
402
+ x-hg-event-id
403
+ x-hg-event
404
+ x-hg-project-id
405
+ x-hg-timestamp
406
+ x-hg-signature
407
+ ```
408
+
409
+ Example callback payload:
410
+
411
+ ```json
412
+ {
413
+ "event_id": "callback_event_xxx",
414
+ "event": "verification.completed",
415
+ "success": true,
416
+ "verified_human": true,
417
+ "verification_level": "orb",
418
+ "unique_for_partner": false,
419
+ "already_verified": true,
420
+ "project_id": "project_xxx",
421
+ "created_at": "2026-06-25T00:00:00.000Z"
422
+ }
423
+ ```
424
+
425
+ ---
426
+
427
+ ## Recommended callback verification
428
+
429
+ Use `verifyCallback` when you want Human Gateway to validate the signature, timestamp, required headers, JSON payload, event id, event type, and project id consistency.
430
+
431
+ ```ts
432
+ import { verifyCallback } from "@human-gateway/sdk/server";
433
+
434
+ export async function POST(request: Request) {
435
+ const body = await request.text();
436
+
437
+ try {
438
+ const callback = verifyCallback({
439
+ body,
440
+ headers: request.headers,
441
+ // Use the callback secret configured for this project in Partner Console.
442
+ // You can generate or rotate it from the project callback settings.
443
+ secret: process.env.HG_CALLBACK_SECRET!,
444
+ expectedProjectId: "project_xxx",
445
+ });
446
+
447
+ if (callback.event === "verification.completed") {
448
+ const payload = callback.payload;
449
+
450
+ if (payload.verified_human === true) {
451
+ // Persist verified state in your backend
452
+ }
453
+ }
454
+
455
+ if (callback.event === "auth.completed") {
456
+ const payload = callback.payload;
457
+
458
+ if (payload.verified_human === true) {
459
+ // Persist or reconcile auth state in your backend
460
+ }
461
+ }
462
+
463
+ return Response.json({ success: true });
464
+ } catch {
465
+ return new Response("Invalid Human Gateway callback", {
466
+ status: 401,
467
+ });
468
+ }
469
+ }
470
+ ```
471
+
472
+ ---
473
+
474
+ ## Low-level signature verification
475
+
476
+ Use `verifyCallbackSignature` only if you want to verify the signature yourself and handle payload/header validation manually.
477
+
478
+ ```ts
479
+ import { verifyCallbackSignature } from "@human-gateway/sdk/server";
480
+
481
+ export async function POST(request: Request) {
482
+ const rawBody = await request.text();
483
+
484
+ const isValid = verifyCallbackSignature({
485
+ rawBody,
486
+ timestamp: request.headers.get("x-hg-timestamp"),
487
+ signature: request.headers.get("x-hg-signature"),
488
+ // Use the callback secret configured for this project in Partner Console.
489
+ // You can generate or rotate it from the project callback settings.
490
+ secret: process.env.HG_CALLBACK_SECRET!,
491
+ });
492
+
493
+ if (!isValid) {
494
+ return new Response("Invalid Human Gateway signature", {
495
+ status: 401,
496
+ });
497
+ }
498
+
499
+ const payload = JSON.parse(rawBody);
500
+
501
+ return Response.json({
502
+ success: true,
503
+ event: payload.event,
504
+ });
505
+ }
506
+ ```
507
+
508
+ ---
509
+
510
+ ## Callback verification errors
511
+
512
+ ```ts
513
+ type HumanGatewayCallbackErrorCode =
514
+ | "callback_missing_body"
515
+ | "callback_missing_secret"
516
+ | "callback_missing_header"
517
+ | "callback_invalid_timestamp"
518
+ | "callback_expired_timestamp"
519
+ | "callback_invalid_signature_format"
520
+ | "callback_invalid_signature"
521
+ | "callback_invalid_json"
522
+ | "callback_invalid_payload"
523
+ | "callback_event_id_mismatch"
524
+ | "callback_event_type_mismatch"
525
+ | "callback_project_id_mismatch";
526
+ ```
527
+
528
+ Example:
529
+
530
+ ```ts
531
+ import {
532
+ HumanGatewayCallbackError,
533
+ verifyCallback,
534
+ } from "@human-gateway/sdk/server";
535
+
536
+ try {
537
+ const callback = verifyCallback({
538
+ body,
539
+ headers,
540
+ secret: process.env.HG_CALLBACK_SECRET!,
541
+ });
542
+ } catch (error) {
543
+ if (error instanceof HumanGatewayCallbackError) {
544
+ console.error("Invalid Human Gateway callback:", error.code);
545
+ }
546
+ }
547
+ ```
548
+
549
+ ---
550
+
551
+ ## SDK error codes
552
+
553
+ ```ts
554
+ type HumanGatewayErrorCode =
555
+ | "popup_blocked"
556
+ | "user_closed"
557
+ | "timeout"
558
+ | "invalid_message"
559
+ | "invalid_origin"
560
+ | "verification_failed"
561
+ | "auth_failed"
562
+ | "unknown_error";
563
+ ```
564
+
565
+ Common handling:
566
+
567
+ ```ts
568
+ import { HumanGateway, HumanGatewayError } from "@human-gateway/sdk";
569
+
570
+ const hg = new HumanGateway({
571
+ projectId: "project_xxx",
572
+ });
573
+
574
+ try {
575
+ const result = await hg.verify({
576
+ actionKey: "hg_verify_action_key_xxx",
577
+ });
578
+ } catch (error) {
579
+ if (error instanceof HumanGatewayError) {
580
+ if (error.code === "user_closed") {
581
+ // User cancelled the flow
582
+ }
583
+
584
+ if (error.code === "popup_blocked") {
585
+ // Ask the user to allow popups
586
+ }
587
+
588
+ if (error.code === "verification_failed") {
589
+ // The hosted verification flow did not complete successfully
590
+ }
591
+ }
592
+ }
593
+ ```
594
+
595
+ ---
596
+
597
+ ## Local development
598
+
599
+ ```ts
600
+ const hg = new HumanGateway({
601
+ projectId: "project_1a7f21ff5e261645",
602
+ environment: "sandbox",
603
+ baseUrl: "http://localhost:3000",
604
+ });
605
+
606
+ await hg.verify({
607
+ actionKey: "hg_verify_action_key_xxx",
608
+ });
609
+
610
+ await hg.auth({
611
+ actionKey: "hg_auth_action_key_xxx",
612
+ });
613
+ ```
614
+
615
+ `baseUrl` overrides the hosted Human Gateway domain. Use it for local testing, previews, or controlled internal validation.
616
+
617
+ ---
618
+
619
+ ## Privacy-first guarantees
620
+
621
+ Human Gateway does not identify the user.
622
+
623
+ It verifies humanity inside a project/action context.
624
+
625
+ The partner may receive:
626
+
627
+ ```txt
628
+ success
629
+ verified_human
630
+ verification_level
631
+ unique_for_partner
632
+ already_verified
633
+ partner_user_id
634
+ auth_session_id
635
+ project_id
636
+ expires_at
637
+ ```
638
+ `verification_level` can be `device`, `document`, `secure_document`, `orb`, or `null`.
639
+
640
+ Human Gateway only returns the value provided by World ID. It does not infer, upgrade, or claim a stronger verification level.
641
+
642
+ The partner does not receive:
643
+
644
+ ```txt
645
+ World ID nullifier
646
+ biometric data
647
+ personal identity
648
+ World proof internals
649
+ Human Gateway internal user object
650
+ raw World ID proof data
651
+ ```
652
+
653
+ ---
654
+
655
+ ## Recommended partner verification flow
656
+
657
+ ```txt
658
+ 1. User clicks "Verify with Human Gateway"
659
+ 2. SDK opens Human Gateway popup
660
+ 3. User completes World ID proof
661
+ 4. Partner frontend receives UX result
662
+ 5. Human Gateway sends signed callback to partner backend
663
+ 6. Partner backend verifies callback
664
+ 7. Partner persists verified status
665
+ 8. Partner hides verification button
666
+ ```
667
+
668
+ ---
669
+
670
+ ## Recommended partner auth flow
671
+
672
+ ```txt
673
+ 1. User clicks "Sign in with Human Gateway"
674
+ 2. SDK opens Human Gateway Auth popup
675
+ 3. User completes World ID proof
676
+ 4. Human Gateway creates a partner-scoped auth session
677
+ 5. Partner frontend receives UX result
678
+ 6. Human Gateway sends signed callback to partner backend
679
+ 7. Partner backend verifies callback
680
+ 8. Partner grants or reconciles app access according to its own session model
681
+ ```
682
+
683
+ ---
684
+
685
+ ## Current alpha status
686
+
687
+ Implemented:
688
+
689
+ * popup verification flow
690
+ * popup auth flow
691
+ * action-specific `hg.verify({ actionKey })`
692
+ * action-specific `hg.auth({ actionKey })`
693
+ * fallback behavior without `actionKey`
694
+ * postMessage result delivery
695
+ * timeout handling
696
+ * user close detection
697
+ * duplicate verify/auth call prevention
698
+ * signed callback verification helper
699
+ * full callback validation helper
700
+ * ESM/CJS builds
701
+ * TypeScript types
702
+ * prepack build protection
703
+ * prepublish typecheck/build protection
704
+
705
+ Planned:
20
706
 
21
- This package currently exists to reserve the official namespace for future Human Gateway SDK releases.
707
+ * iframe modal mode
708
+ * redirect fallback
709
+ * React helper
710
+ * expanded usage/session events
711
+ * public package release
@@ -0,0 +1,2 @@
1
+ var t=class extends Error{constructor(e,a){super(a),this.name="HumanGatewayError",this.code=e}},n=class extends Error{constructor(e,a){super(a),this.name="HumanGatewayCallbackError",this.code=e}};export{t as a,n as b};
2
+ //# sourceMappingURL=chunk-GJKDROWD.js.map