@polyguard/sdk 1.5.0 → 1.5.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.
Files changed (134) hide show
  1. package/LICENSE +200 -0
  2. package/README.md +328 -0
  3. package/package.json +7 -3
  4. package/coverage/base.css +0 -224
  5. package/coverage/block-navigation.js +0 -87
  6. package/coverage/clover.xml +0 -268
  7. package/coverage/coverage-final.json +0 -8
  8. package/coverage/favicon.png +0 -0
  9. package/coverage/index.html +0 -131
  10. package/coverage/prettify.css +0 -1
  11. package/coverage/prettify.js +0 -2
  12. package/coverage/sort-arrow-sprite.png +0 -0
  13. package/coverage/sorter.js +0 -210
  14. package/coverage/src/PolyguardClient.js.html +0 -160
  15. package/coverage/src/PolyguardWebsocketClientImpl.js.html +0 -634
  16. package/coverage/src/__tests__/helpers/fixtures.js.html +0 -166
  17. package/coverage/src/__tests__/helpers/index.html +0 -131
  18. package/coverage/src/__tests__/helpers/mockWebSocket.js.html +0 -283
  19. package/coverage/src/index.html +0 -176
  20. package/coverage/src/messageHandler.js.html +0 -448
  21. package/coverage/src/ticketService.js.html +0 -157
  22. package/coverage/src/ui.js.html +0 -349
  23. package/dist/sdk.global.js +0 -11256
  24. package/scripts/regenerate-client.sh +0 -59
  25. package/src/PolyguardClient.js +0 -25
  26. package/src/PolyguardWebsocketClientImpl.js +0 -198
  27. package/src/__tests__/PolyguardClient.test.js +0 -65
  28. package/src/__tests__/PolyguardWebsocketClientImpl.test.js +0 -617
  29. package/src/__tests__/helpers/fixtures.js +0 -27
  30. package/src/__tests__/helpers/mockWebSocket.js +0 -66
  31. package/src/__tests__/server.test.js +0 -148
  32. package/src/__tests__/sidebar.test.js +0 -289
  33. package/src/browser.js +0 -9
  34. package/src/generated/.babelrc +0 -33
  35. package/src/generated/.openapi-generator/FILES +0 -63
  36. package/src/generated/.openapi-generator/VERSION +0 -1
  37. package/src/generated/.openapi-generator-ignore +0 -23
  38. package/src/generated/.travis.yml +0 -5
  39. package/src/generated/README.md +0 -211
  40. package/src/generated/docs/ApiControllersPslStirCallRequest.md +0 -18
  41. package/src/generated/docs/ApiModelsApiCallModelsCallRequest.md +0 -12
  42. package/src/generated/docs/AppId.md +0 -8
  43. package/src/generated/docs/AppleApi.md +0 -88
  44. package/src/generated/docs/AuthApi.md +0 -1464
  45. package/src/generated/docs/BlockingApi.md +0 -208
  46. package/src/generated/docs/CallsApi.md +0 -140
  47. package/src/generated/docs/Certainty.md +0 -8
  48. package/src/generated/docs/CreateLinkRequest.md +0 -12
  49. package/src/generated/docs/DefaultApi.md +0 -128
  50. package/src/generated/docs/HTTPValidationError.md +0 -9
  51. package/src/generated/docs/InviteRequestModel.md +0 -10
  52. package/src/generated/docs/JWTRequest.md +0 -11
  53. package/src/generated/docs/LinksApi.md +0 -162
  54. package/src/generated/docs/NumberVerification.md +0 -10
  55. package/src/generated/docs/SdkApi.md +0 -54
  56. package/src/generated/docs/SecureLinksApi.md +0 -614
  57. package/src/generated/docs/StartAttestationRequest.md +0 -9
  58. package/src/generated/docs/StartMeetingRequest.md +0 -9
  59. package/src/generated/docs/StirApi.md +0 -52
  60. package/src/generated/docs/TwilioApi.md +0 -138
  61. package/src/generated/docs/UsersApi.md +0 -362
  62. package/src/generated/docs/ValidationError.md +0 -11
  63. package/src/generated/docs/ValidationErrorLocInner.md +0 -8
  64. package/src/generated/docs/VeriffApi.md +0 -188
  65. package/src/generated/docs/VeriffSessionRequest.md +0 -10
  66. package/src/generated/docs/VerifyRequest.md +0 -10
  67. package/src/generated/docs/WellKnownApi.md +0 -128
  68. package/src/generated/docs/ZoomApi.md +0 -848
  69. package/src/generated/git_push.sh +0 -57
  70. package/src/generated/mocha.opts +0 -1
  71. package/src/generated/package.json +0 -46
  72. package/src/generated/src/ApiClient.js +0 -677
  73. package/src/generated/src/api/AppleApi.js +0 -109
  74. package/src/generated/src/api/AuthApi.js +0 -1512
  75. package/src/generated/src/api/BlockingApi.js +0 -217
  76. package/src/generated/src/api/CallsApi.js +0 -164
  77. package/src/generated/src/api/DefaultApi.js +0 -145
  78. package/src/generated/src/api/LinksApi.js +0 -195
  79. package/src/generated/src/api/SdkApi.js +0 -81
  80. package/src/generated/src/api/SecureLinksApi.js +0 -670
  81. package/src/generated/src/api/StirApi.js +0 -80
  82. package/src/generated/src/api/TwilioApi.js +0 -158
  83. package/src/generated/src/api/UsersApi.js +0 -375
  84. package/src/generated/src/api/VeriffApi.js +0 -209
  85. package/src/generated/src/api/WellKnownApi.js +0 -145
  86. package/src/generated/src/api/ZoomApi.js +0 -823
  87. package/src/generated/src/index.js +0 -244
  88. package/src/generated/src/model/ApiControllersPslStirCallRequest.js +0 -211
  89. package/src/generated/src/model/ApiModelsApiCallModelsCallRequest.js +0 -119
  90. package/src/generated/src/model/CreateLinkRequest.js +0 -131
  91. package/src/generated/src/model/HTTPValidationError.js +0 -94
  92. package/src/generated/src/model/InviteRequestModel.js +0 -109
  93. package/src/generated/src/model/JWTRequest.js +0 -113
  94. package/src/generated/src/model/NumberVerification.js +0 -107
  95. package/src/generated/src/model/StartAttestationRequest.js +0 -95
  96. package/src/generated/src/model/StartMeetingRequest.js +0 -95
  97. package/src/generated/src/model/ValidationError.js +0 -130
  98. package/src/generated/src/model/VeriffSessionRequest.js +0 -107
  99. package/src/generated/src/model/VerifyRequest.js +0 -109
  100. package/src/generated/test/api/AppleApi.spec.js +0 -73
  101. package/src/generated/test/api/AuthApi.spec.js +0 -353
  102. package/src/generated/test/api/BlockingApi.spec.js +0 -103
  103. package/src/generated/test/api/CallsApi.spec.js +0 -83
  104. package/src/generated/test/api/DefaultApi.spec.js +0 -73
  105. package/src/generated/test/api/LinksApi.spec.js +0 -83
  106. package/src/generated/test/api/SdkApi.spec.js +0 -63
  107. package/src/generated/test/api/SecureLinksApi.spec.js +0 -143
  108. package/src/generated/test/api/StirApi.spec.js +0 -63
  109. package/src/generated/test/api/TwilioApi.spec.js +0 -83
  110. package/src/generated/test/api/UsersApi.spec.js +0 -133
  111. package/src/generated/test/api/VeriffApi.spec.js +0 -93
  112. package/src/generated/test/api/WellKnownApi.spec.js +0 -83
  113. package/src/generated/test/api/ZoomApi.spec.js +0 -213
  114. package/src/generated/test/model/ApiControllersPslStirCallRequest.spec.js +0 -119
  115. package/src/generated/test/model/ApiModelsApiCallModelsCallRequest.spec.js +0 -83
  116. package/src/generated/test/model/AppId.spec.js +0 -59
  117. package/src/generated/test/model/Certainty.spec.js +0 -59
  118. package/src/generated/test/model/CreateLinkRequest.spec.js +0 -83
  119. package/src/generated/test/model/HTTPValidationError.spec.js +0 -65
  120. package/src/generated/test/model/InviteRequestModel.spec.js +0 -71
  121. package/src/generated/test/model/JWTRequest.spec.js +0 -77
  122. package/src/generated/test/model/NumberVerification.spec.js +0 -71
  123. package/src/generated/test/model/StartAttestationRequest.spec.js +0 -65
  124. package/src/generated/test/model/StartMeetingRequest.spec.js +0 -65
  125. package/src/generated/test/model/ValidationError.spec.js +0 -77
  126. package/src/generated/test/model/ValidationErrorLocInner.spec.js +0 -59
  127. package/src/generated/test/model/VeriffSessionRequest.spec.js +0 -71
  128. package/src/generated/test/model/VerifyRequest.spec.js +0 -71
  129. package/src/index.js +0 -16
  130. package/src/messageHandler.js +0 -121
  131. package/src/server.js +0 -91
  132. package/src/ticketService.js +0 -28
  133. package/src/ui.js +0 -88
  134. package/vitest.config.js +0 -10
@@ -1,66 +0,0 @@
1
- /**
2
- * Mock for reconnecting-websocket.
3
- * Captures the URL/protocols/options passed to the constructor and
4
- * exposes helpers to drive the message handler under test.
5
- */
6
- export class MockReconnectingWebSocket {
7
- static instances = [];
8
-
9
- constructor(url, protocols, options) {
10
- this.url = url;
11
- this.protocols = protocols;
12
- this.options = options;
13
- this._listeners = {};
14
- this.readyState = 1; // OPEN
15
- this.sent = [];
16
- MockReconnectingWebSocket.instances.push(this);
17
- }
18
-
19
- addEventListener(type, handler) {
20
- if (!this._listeners[type]) this._listeners[type] = [];
21
- this._listeners[type].push(handler);
22
- }
23
-
24
- removeEventListener(type, handler) {
25
- if (!this._listeners[type]) return;
26
- this._listeners[type] = this._listeners[type].filter(h => h !== handler);
27
- }
28
-
29
- send(data) {
30
- this.sent.push(data);
31
- }
32
-
33
- close() {
34
- this.readyState = 3; // CLOSED
35
- this._emit('close', {});
36
- }
37
-
38
- // --- Test helpers ---
39
-
40
- simulateMessage(data) {
41
- this._emit('message', { data: JSON.stringify(data) });
42
- }
43
-
44
- simulateError() {
45
- this._emit('error', {});
46
- }
47
-
48
- simulateClose() {
49
- this._emit('close', {});
50
- }
51
-
52
- _emit(type, event) {
53
- const handlers = this._listeners[type] || [];
54
- for (const h of handlers) {
55
- h(event);
56
- }
57
- }
58
-
59
- static reset() {
60
- MockReconnectingWebSocket.instances = [];
61
- }
62
-
63
- static latest() {
64
- return MockReconnectingWebSocket.instances[MockReconnectingWebSocket.instances.length - 1];
65
- }
66
- }
@@ -1,148 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- import { createProxyHandler } from '../server.js';
3
-
4
- function makeRequest(method, url, { headers = {}, body = null } = {}) {
5
- const init = { method, headers };
6
- if (body !== null) init.body = typeof body === 'string' ? body : JSON.stringify(body);
7
- return new Request(url, init);
8
- }
9
-
10
- function stubFetch(responseOpts = {}) {
11
- const { status = 200, body = '{"ok":true}', headers = { 'content-type': 'application/json' } } = responseOpts;
12
- const mock = vi.fn().mockImplementation(async () => new Response(body, { status, headers }));
13
- vi.stubGlobal('fetch', mock);
14
- return mock;
15
- }
16
-
17
- describe('createProxyHandler', () => {
18
- beforeEach(() => {
19
- vi.restoreAllMocks();
20
- });
21
-
22
- it('throws when apiKey is missing', () => {
23
- expect(() => createProxyHandler({ apiServer: 'api.polyguard.ai' })).toThrow(/apiKey is required/);
24
- });
25
-
26
- it('throws when apiServer is falsy', () => {
27
- expect(() => createProxyHandler({ apiKey: 'pgk_live_x.y', apiServer: '' })).toThrow(/apiServer is required/);
28
- });
29
-
30
- it('returns 404 for paths not in the allowlist', async () => {
31
- stubFetch();
32
- const handler = createProxyHandler({ apiKey: 'pgk_live_x.y', apiServer: 'api.polyguard.ai' });
33
- const req = makeRequest('GET', 'http://localhost/api/polyguard/account/1/apps/3/api-keys');
34
- const res = await handler(req);
35
- expect(res.status).toBe(404);
36
- });
37
-
38
- it('returns 404 for an allowlisted prefix used with the wrong HTTP method', async () => {
39
- stubFetch();
40
- const handler = createProxyHandler({ apiKey: 'pgk_live_x.y', apiServer: 'api.polyguard.ai' });
41
- const req = makeRequest('GET', 'http://localhost/api/polyguard/v2/ticket/3');
42
- const res = await handler(req);
43
- expect(res.status).toBe(404);
44
- });
45
-
46
- it('forwards POST /v2/ticket/* with x-pg-api-key injected', async () => {
47
- const fetchMock = stubFetch();
48
- const handler = createProxyHandler({ apiKey: 'pgk_live_x.y', apiServer: 'api.polyguard.ai' });
49
- const req = makeRequest('POST', 'http://localhost/api/polyguard/v2/ticket/3', {
50
- headers: { 'content-type': 'application/json' },
51
- body: { requiredProofs: ['name'], scanType: 'single' },
52
- });
53
- const res = await handler(req);
54
- expect(res.status).toBe(200);
55
- expect(fetchMock).toHaveBeenCalledOnce();
56
- const [forwardedUrl, init] = fetchMock.mock.calls[0];
57
- expect(forwardedUrl).toBe('https://api.polyguard.ai/v2/ticket/3');
58
- expect(init.method).toBe('POST');
59
- const headers = new Headers(init.headers);
60
- expect(headers.get('x-pg-api-key')).toBe('pgk_live_x.y');
61
- });
62
-
63
- it('strips client-supplied x-pg-api-key before injecting', async () => {
64
- const fetchMock = stubFetch();
65
- const handler = createProxyHandler({ apiKey: 'pgk_live_real.secret', apiServer: 'api.polyguard.ai' });
66
- const req = makeRequest('POST', 'http://localhost/api/polyguard/v2/ticket/3', {
67
- headers: { 'x-pg-api-key': 'pgk_live_attacker.smuggled', 'content-type': 'application/json' },
68
- body: {},
69
- });
70
- await handler(req);
71
- const init = fetchMock.mock.calls[0][1];
72
- const headers = new Headers(init.headers);
73
- expect(headers.get('x-pg-api-key')).toBe('pgk_live_real.secret');
74
- });
75
-
76
- it('strips client-supplied authorization header', async () => {
77
- const fetchMock = stubFetch();
78
- const handler = createProxyHandler({ apiKey: 'pgk_live_x.y', apiServer: 'api.polyguard.ai' });
79
- const req = makeRequest('POST', 'http://localhost/api/polyguard/v2/ticket/3', {
80
- headers: { authorization: 'Bearer pgk_live_attacker.smuggled', 'content-type': 'application/json' },
81
- body: {},
82
- });
83
- await handler(req);
84
- const init = fetchMock.mock.calls[0][1];
85
- const headers = new Headers(init.headers);
86
- expect(headers.get('authorization')).toBeNull();
87
- });
88
-
89
- it('preserves query string when forwarding', async () => {
90
- const fetchMock = stubFetch();
91
- const handler = createProxyHandler({ apiKey: 'pgk_live_x.y', apiServer: 'api.polyguard.ai' });
92
- const req = makeRequest('GET', 'http://localhost/api/polyguard/v2/preview/3/link-abc?format=svg');
93
- await handler(req);
94
- expect(fetchMock.mock.calls[0][0]).toBe('https://api.polyguard.ai/v2/preview/3/link-abc?format=svg');
95
- });
96
-
97
- it('forwards PUT /link/* (link creation)', async () => {
98
- const fetchMock = stubFetch();
99
- const handler = createProxyHandler({ apiKey: 'pgk_live_x.y', apiServer: 'api.polyguard.ai' });
100
- const req = makeRequest('PUT', 'http://localhost/api/polyguard/link/3', {
101
- headers: { 'content-type': 'application/json' },
102
- body: { type: 'login' },
103
- });
104
- const res = await handler(req);
105
- expect(res.status).toBe(200);
106
- expect(fetchMock.mock.calls[0][0]).toBe('https://api.polyguard.ai/link/3');
107
- });
108
-
109
- it('honors a custom allowedPaths list', async () => {
110
- stubFetch();
111
- const handler = createProxyHandler({
112
- apiKey: 'pgk_live_x.y',
113
- apiServer: 'api.polyguard.ai',
114
- allowedPaths: ['POST /v2/ticket/'],
115
- });
116
- const denied = await handler(makeRequest('PUT', 'http://localhost/api/polyguard/link/3'));
117
- expect(denied.status).toBe(404);
118
- const allowed = await handler(makeRequest('POST', 'http://localhost/api/polyguard/v2/ticket/3', { body: {} }));
119
- expect(allowed.status).toBe(200);
120
- });
121
-
122
- it('honors a custom pathPrefix', async () => {
123
- const fetchMock = stubFetch();
124
- const handler = createProxyHandler({
125
- apiKey: 'pgk_live_x.y',
126
- apiServer: 'api.polyguard.ai',
127
- pathPrefix: '/custom/proxy',
128
- });
129
- await handler(makeRequest('POST', 'http://localhost/custom/proxy/v2/ticket/3', { body: {} }));
130
- expect(fetchMock.mock.calls[0][0]).toBe('https://api.polyguard.ai/v2/ticket/3');
131
- });
132
-
133
- it('strips hop-by-hop response headers and set-cookie', async () => {
134
- stubFetch({
135
- headers: {
136
- 'content-type': 'application/json',
137
- 'set-cookie': 'session=abc; path=/',
138
- 'transfer-encoding': 'chunked',
139
- 'x-custom': 'visible',
140
- },
141
- });
142
- const handler = createProxyHandler({ apiKey: 'pgk_live_x.y', apiServer: 'api.polyguard.ai' });
143
- const res = await handler(makeRequest('POST', 'http://localhost/api/polyguard/v2/ticket/3', { body: {} }));
144
- expect(res.headers.get('set-cookie')).toBeNull();
145
- expect(res.headers.get('transfer-encoding')).toBeNull();
146
- expect(res.headers.get('x-custom')).toBe('visible');
147
- });
148
- });
@@ -1,289 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
- import { buildFakeJwt, DEFAULT_PARAMS, mockTicketResponse } from './helpers/fixtures.js';
3
- import { MockReconnectingWebSocket } from './helpers/mockWebSocket.js';
4
-
5
- // ---- Module mocks ----
6
-
7
- const { MockApiClient, generatedMock, mockQRCode } = vi.hoisted(() => {
8
- class MockApiClient {
9
- constructor() {
10
- this.basePath = '';
11
- this.authentications = { bearerAuth: { apiKey: null } };
12
- }
13
- }
14
-
15
- const generatedMock = { ApiClient: MockApiClient };
16
- const apiClassNames = [
17
- 'BlockingApi', 'CallsApi', 'DefaultApi', 'LinksApi', 'SdkApi',
18
- 'SecureLinksApi', 'StirApi', 'TwilioApi', 'UsersApi', 'VeriffApi',
19
- 'WellKnownApi', 'ZoomApi',
20
- ];
21
- for (const name of apiClassNames) {
22
- generatedMock[name] = class {
23
- constructor(apiClient) { this._apiClient = apiClient; }
24
- };
25
- }
26
-
27
- const mockQRCode = {
28
- toString: null,
29
- };
30
-
31
- return { MockApiClient, generatedMock, mockQRCode };
32
- });
33
-
34
- vi.mock('../generated/src', () => generatedMock);
35
-
36
- vi.mock('reconnecting-websocket', async () => {
37
- const { MockReconnectingWebSocket } = await import('./helpers/mockWebSocket.js');
38
- return { default: MockReconnectingWebSocket };
39
- });
40
-
41
- vi.mock('qrcode', () => ({
42
- default: mockQRCode,
43
- }));
44
-
45
- const { PolyguardWebsocketClientImpl } = await import('../PolyguardWebsocketClientImpl.js');
46
-
47
- // ---- Helpers ----
48
-
49
- async function flushMicrotasks() {
50
- await new Promise(resolve => setTimeout(resolve, 0));
51
- }
52
-
53
- function stubFetch(ticket = 'test-ticket-123', ok = true) {
54
- const mock = vi.fn().mockResolvedValue(mockTicketResponse(ticket, ok));
55
- vi.stubGlobal('fetch', mock);
56
- return mock;
57
- }
58
-
59
- function setProtocol(protocol) {
60
- Object.defineProperty(window, 'location', {
61
- value: { protocol, assign: vi.fn(), href: '' },
62
- writable: true,
63
- configurable: true,
64
- });
65
- }
66
-
67
- function setUserAgent(ua) {
68
- Object.defineProperty(navigator, 'userAgent', {
69
- value: ua,
70
- writable: true,
71
- configurable: true,
72
- });
73
- }
74
-
75
- async function startVerifyAndGetWs(client, target = null, rawJwt = false) {
76
- const promise = client.verify(target, rawJwt);
77
- await flushMicrotasks();
78
- const ws = MockReconnectingWebSocket.latest();
79
- return { promise, ws };
80
- }
81
-
82
- function setCookie(name, value) {
83
- Object.defineProperty(document, 'cookie', {
84
- value: `${name}=${value}; other=stuff`,
85
- writable: true,
86
- configurable: true,
87
- });
88
- }
89
-
90
- function clearCookies() {
91
- Object.defineProperty(document, 'cookie', {
92
- value: '',
93
- writable: true,
94
- configurable: true,
95
- });
96
- }
97
-
98
- // ---- Tests ----
99
-
100
- describe('sidebarUrl feature', () => {
101
- beforeEach(() => {
102
- vi.clearAllMocks();
103
- MockReconnectingWebSocket.reset();
104
- setProtocol('https:');
105
- setUserAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)');
106
- stubFetch();
107
- mockQRCode.toString = vi.fn((data, opts, cb) => cb(null, '<svg>mock-qr</svg>'));
108
- clearCookies();
109
- });
110
-
111
- afterEach(() => {
112
- vi.restoreAllMocks();
113
- document.body.innerHTML = '';
114
- });
115
-
116
- describe('constructor', () => {
117
- it('stores sidebarUrl when provided', () => {
118
- const client = new PolyguardWebsocketClientImpl({
119
- ...DEFAULT_PARAMS,
120
- sidebarUrl: 'https://teams.polyguard.ai/ms-teams/sidebar-standalone',
121
- });
122
- expect(client.sidebarUrl).toBe('https://teams.polyguard.ai/ms-teams/sidebar-standalone');
123
- });
124
-
125
- it('sidebarUrl is undefined when not provided', () => {
126
- const client = new PolyguardWebsocketClientImpl(DEFAULT_PARAMS);
127
- expect(client.sidebarUrl).toBeUndefined();
128
- });
129
- });
130
-
131
- describe('without sidebarUrl - existing behavior unchanged', () => {
132
- it('jwt with redirect_url resolves normally', async () => {
133
- const client = new PolyguardWebsocketClientImpl(DEFAULT_PARAMS);
134
- const fakeJwt = buildFakeJwt({ redirect_url: 'https://teams.microsoft.com/meet/123' });
135
- const { promise, ws } = await startVerifyAndGetWs(client);
136
- ws.simulateMessage({ jwt: fakeJwt });
137
- const result = await promise;
138
- expect(result).toBe(fakeJwt);
139
- });
140
-
141
- it('does not call window.open', async () => {
142
- const openSpy = vi.fn();
143
- vi.stubGlobal('open', openSpy);
144
- const client = new PolyguardWebsocketClientImpl(DEFAULT_PARAMS);
145
- const fakeJwt = buildFakeJwt({ redirect_url: 'https://teams.microsoft.com/meet/123' });
146
- const { promise, ws } = await startVerifyAndGetWs(client);
147
- ws.simulateMessage({ jwt: fakeJwt });
148
- await promise;
149
- expect(openSpy).not.toHaveBeenCalled();
150
- });
151
- });
152
-
153
- describe('with sidebarUrl and pg_msft_session cookie (authenticated user)', () => {
154
- it('auto-redirects without showing a button', async () => {
155
- setCookie('pg_msft_session', '1');
156
- const client = new PolyguardWebsocketClientImpl({
157
- ...DEFAULT_PARAMS,
158
- sidebarUrl: 'https://teams.polyguard.ai/ms-teams/sidebar-standalone',
159
- link_uuid: 'link-abc',
160
- });
161
- document.body.innerHTML = '<div id="test-target"></div>';
162
- const jwtClaims = { redirect_url: 'https://teams.microsoft.com/meet/123' };
163
- const { promise, ws } = await startVerifyAndGetWs(client, 'test-target');
164
- ws.simulateMessage({ jwt: jwtClaims });
165
- await promise;
166
- expect(window.location.assign).toHaveBeenCalledWith('https://teams.microsoft.com/meet/123');
167
- });
168
-
169
- it('does not render a join button', async () => {
170
- setCookie('pg_msft_session', '1');
171
- const client = new PolyguardWebsocketClientImpl({
172
- ...DEFAULT_PARAMS,
173
- sidebarUrl: 'https://teams.polyguard.ai/ms-teams/sidebar-standalone',
174
- link_uuid: 'link-abc',
175
- });
176
- document.body.innerHTML = '<div id="test-target"></div>';
177
- const jwtClaims = { redirect_url: 'https://teams.microsoft.com/meet/123' };
178
- const { promise, ws } = await startVerifyAndGetWs(client, 'test-target');
179
- ws.simulateMessage({ jwt: jwtClaims });
180
- await promise;
181
- expect(document.querySelector('#polyguard-join-meeting')).toBeNull();
182
- });
183
- });
184
-
185
- describe('with sidebarUrl and NO cookie (anonymous user)', () => {
186
- it('renders a join button instead of auto-redirecting', async () => {
187
- clearCookies();
188
- const client = new PolyguardWebsocketClientImpl({
189
- ...DEFAULT_PARAMS,
190
- sidebarUrl: 'https://teams.polyguard.ai/ms-teams/sidebar-standalone',
191
- link_uuid: 'link-abc',
192
- });
193
- document.body.innerHTML = '<div id="test-target"></div>';
194
- const jwtClaims = { redirect_url: 'https://teams.microsoft.com/meet/123' };
195
- const { promise, ws } = await startVerifyAndGetWs(client, 'test-target');
196
- ws.simulateMessage({ jwt: jwtClaims });
197
- // Should not have redirected yet
198
- expect(window.location.assign).not.toHaveBeenCalled();
199
- // Should show join button
200
- const btn = document.querySelector('#polyguard-join-meeting');
201
- expect(btn).not.toBeNull();
202
- // Resolve by clicking the button
203
- btn.click();
204
- await promise;
205
- });
206
-
207
- it('clicking join button opens sidebar popup', async () => {
208
- clearCookies();
209
- const openSpy = vi.fn().mockReturnValue({});
210
- vi.stubGlobal('open', openSpy);
211
- const client = new PolyguardWebsocketClientImpl({
212
- ...DEFAULT_PARAMS,
213
- sidebarUrl: 'https://teams.polyguard.ai/ms-teams/sidebar-standalone',
214
- link_uuid: 'link-abc',
215
- });
216
- document.body.innerHTML = '<div id="test-target"></div>';
217
- const jwtClaims = { redirect_url: 'https://teams.microsoft.com/meet/123' };
218
- const { promise, ws } = await startVerifyAndGetWs(client, 'test-target');
219
- ws.simulateMessage({ jwt: jwtClaims });
220
- const btn = document.querySelector('#polyguard-join-meeting');
221
- btn.click();
222
- await promise;
223
- expect(openSpy).toHaveBeenCalledWith(
224
- 'https://teams.polyguard.ai/ms-teams/sidebar-standalone?linkUuid=link-abc',
225
- 'polyguard-sidebar',
226
- expect.stringContaining('width=320')
227
- );
228
- });
229
-
230
- it('clicking join button redirects to meeting', async () => {
231
- clearCookies();
232
- vi.stubGlobal('open', vi.fn().mockReturnValue({}));
233
- const client = new PolyguardWebsocketClientImpl({
234
- ...DEFAULT_PARAMS,
235
- sidebarUrl: 'https://teams.polyguard.ai/ms-teams/sidebar-standalone',
236
- link_uuid: 'link-abc',
237
- });
238
- document.body.innerHTML = '<div id="test-target"></div>';
239
- const jwtClaims = { redirect_url: 'https://teams.microsoft.com/meet/123' };
240
- const { promise, ws } = await startVerifyAndGetWs(client, 'test-target');
241
- ws.simulateMessage({ jwt: jwtClaims });
242
- document.querySelector('#polyguard-join-meeting').click();
243
- await promise;
244
- expect(window.location.assign).toHaveBeenCalledWith('https://teams.microsoft.com/meet/123');
245
- });
246
-
247
- it('button survives a late WebSocket close event (race regression)', async () => {
248
- // Real browsers dispatch the 'close' event asynchronously after ws.close(),
249
- // so it lands after the synchronous button append. If the close listener's
250
- // cleanup() runs in that window, it wipes the qrDiv — and the button with it.
251
- // markClosed() in the message handler must defuse the close listener.
252
- clearCookies();
253
- vi.stubGlobal('open', vi.fn().mockReturnValue({}));
254
- const client = new PolyguardWebsocketClientImpl({
255
- ...DEFAULT_PARAMS,
256
- sidebarUrl: 'https://teams.polyguard.ai/ms-teams/sidebar-standalone',
257
- link_uuid: 'link-abc',
258
- });
259
- document.body.innerHTML = '<div id="test-target"></div>';
260
- const jwtClaims = { redirect_url: 'https://teams.microsoft.com/meet/123' };
261
- const { promise, ws } = await startVerifyAndGetWs(client, 'test-target');
262
- ws.simulateMessage({ jwt: jwtClaims });
263
- expect(document.querySelector('#polyguard-join-meeting')).not.toBeNull();
264
- // Mimic a real browser dispatching close on the next tick (after the message handler returned).
265
- ws.simulateClose();
266
- expect(document.querySelector('#polyguard-join-meeting')).not.toBeNull();
267
- document.querySelector('#polyguard-join-meeting').click();
268
- await promise;
269
- });
270
- });
271
-
272
- describe('with sidebarUrl but no redirect_url in JWT (non-meeting links)', () => {
273
- it('resolves normally without button or redirect', async () => {
274
- clearCookies();
275
- const client = new PolyguardWebsocketClientImpl({
276
- ...DEFAULT_PARAMS,
277
- sidebarUrl: 'https://teams.polyguard.ai/ms-teams/sidebar-standalone',
278
- link_uuid: 'link-abc',
279
- });
280
- const jwtClaims = { confirmation_code: 'ABC123' };
281
- const { promise, ws } = await startVerifyAndGetWs(client);
282
- // No redirect_url in the JWT claims
283
- ws.simulateMessage({ jwt: jwtClaims });
284
- const result = await promise;
285
- expect(result).toEqual(jwtClaims);
286
- expect(window.location.assign).not.toHaveBeenCalled();
287
- });
288
- });
289
- });
package/src/browser.js DELETED
@@ -1,9 +0,0 @@
1
- /**
2
- * Browser/script-tag entry point. Exposes a single global (Polyguard) when built as IIFE.
3
- * Use this build via: <script src="https://cdn.polyguard.ai/sdk/latest/sdk.js"></script>
4
- * Named exports become window.Polyguard.Client, window.Polyguard.AuthApi, etc.
5
- */
6
- import { PolyguardClient } from './PolyguardClient.js';
7
-
8
- export { PolyguardClient as Client };
9
- export * from './generated/src/index.js';
@@ -1,33 +0,0 @@
1
- {
2
- "presets": [
3
- "@babel/preset-env"
4
- ],
5
- "plugins": [
6
- "@babel/plugin-syntax-dynamic-import",
7
- "@babel/plugin-syntax-import-meta",
8
- "@babel/plugin-proposal-class-properties",
9
- "@babel/plugin-proposal-json-strings",
10
- [
11
- "@babel/plugin-proposal-decorators",
12
- {
13
- "legacy": true
14
- }
15
- ],
16
- "@babel/plugin-proposal-function-sent",
17
- "@babel/plugin-proposal-export-namespace-from",
18
- "@babel/plugin-proposal-numeric-separator",
19
- "@babel/plugin-proposal-throw-expressions",
20
- "@babel/plugin-proposal-export-default-from",
21
- "@babel/plugin-proposal-logical-assignment-operators",
22
- "@babel/plugin-proposal-optional-chaining",
23
- [
24
- "@babel/plugin-proposal-pipeline-operator",
25
- {
26
- "proposal": "minimal"
27
- }
28
- ],
29
- "@babel/plugin-proposal-nullish-coalescing-operator",
30
- "@babel/plugin-proposal-do-expressions",
31
- "@babel/plugin-proposal-function-bind"
32
- ]
33
- }
@@ -1,63 +0,0 @@
1
- .babelrc
2
- .gitignore
3
- .travis.yml
4
- README.md
5
- docs/ApiControllersPslStirCallRequest.md
6
- docs/ApiModelsApiCallModelsCallRequest.md
7
- docs/AppId.md
8
- docs/BlockingApi.md
9
- docs/CallsApi.md
10
- docs/Certainty.md
11
- docs/CreateLinkRequest.md
12
- docs/DefaultApi.md
13
- docs/HTTPValidationError.md
14
- docs/InviteRequestModel.md
15
- docs/JWTRequest.md
16
- docs/LinksApi.md
17
- docs/NumberVerification.md
18
- docs/SdkApi.md
19
- docs/SecureLinksApi.md
20
- docs/StartAttestationRequest.md
21
- docs/StartMeetingRequest.md
22
- docs/StirApi.md
23
- docs/TwilioApi.md
24
- docs/UsersApi.md
25
- docs/ValidationError.md
26
- docs/ValidationErrorLocInner.md
27
- docs/VeriffApi.md
28
- docs/VeriffSessionRequest.md
29
- docs/VerifyRequest.md
30
- docs/WellKnownApi.md
31
- docs/ZoomApi.md
32
- git_push.sh
33
- mocha.opts
34
- package.json
35
- src/ApiClient.js
36
- src/api/BlockingApi.js
37
- src/api/CallsApi.js
38
- src/api/DefaultApi.js
39
- src/api/LinksApi.js
40
- src/api/SdkApi.js
41
- src/api/SecureLinksApi.js
42
- src/api/StirApi.js
43
- src/api/TwilioApi.js
44
- src/api/UsersApi.js
45
- src/api/VeriffApi.js
46
- src/api/WellKnownApi.js
47
- src/api/ZoomApi.js
48
- src/index.js
49
- src/model/ApiControllersPslStirCallRequest.js
50
- src/model/ApiModelsApiCallModelsCallRequest.js
51
- src/model/AppId.js
52
- src/model/Certainty.js
53
- src/model/CreateLinkRequest.js
54
- src/model/HTTPValidationError.js
55
- src/model/InviteRequestModel.js
56
- src/model/JWTRequest.js
57
- src/model/NumberVerification.js
58
- src/model/StartAttestationRequest.js
59
- src/model/StartMeetingRequest.js
60
- src/model/ValidationError.js
61
- src/model/ValidationErrorLocInner.js
62
- src/model/VeriffSessionRequest.js
63
- src/model/VerifyRequest.js
@@ -1 +0,0 @@
1
- 7.14.0-SNAPSHOT
@@ -1,23 +0,0 @@
1
- # OpenAPI Generator Ignore
2
- # Generated by openapi-generator https://github.com/openapitools/openapi-generator
3
-
4
- # Use this file to prevent files from being overwritten by the generator.
5
- # The patterns follow closely to .gitignore or .dockerignore.
6
-
7
- # As an example, the C# client generator defines ApiClient.cs.
8
- # You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
9
- #ApiClient.cs
10
-
11
- # You can match any string of characters against a directory, file or extension with a single asterisk (*):
12
- #foo/*/qux
13
- # The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
14
-
15
- # You can recursively match patterns against a directory, file or extension with a double asterisk (**):
16
- #foo/**/qux
17
- # This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
18
-
19
- # You can also negate patterns with an exclamation (!).
20
- # For example, you can ignore all files in a docs folder with the file extension .md:
21
- #docs/*.md
22
- # Then explicitly reverse the ignore rule for a single file:
23
- #!docs/README.md
@@ -1,5 +0,0 @@
1
- language: node_js
2
- cache: npm
3
- node_js:
4
- - "6"
5
- - "6.1"