@tanqory/plugin-sdk 0.6.1 → 0.6.3

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Tanqory Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,aAAa,EAAoB,MAAM,qBAAqB,CAAA;AAG7F;;;;;;GAMG;AAEH,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAA;AAE5D,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,gBAAgB,CAAA;IACxB,KAAK,EAAE,OAAO,CAAA;IACd,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,6BAA6B;IAC7B,KAAK,EAAE,aAAa,GAAG,IAAI,CAAA;IAC3B,kEAAkE;IAClE,GAAG,EAAE,WAAW,GAAG,IAAI,CAAA;IACvB,6EAA6E;IAC7E,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAA;IAC/B,sFAAsF;IACtF,KAAK,EAAE,CAAC,OAAO,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;CAC5F;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IAC7F,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IAC3D,KAAK,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IAC5D,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;CAC9C;AAED,MAAM,WAAW,oBAAoB;IACnC;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;CAC9B;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,eAAe,CA2EjF"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,aAAa,EAAoB,MAAM,qBAAqB,CAAA;AAG7F;;;;;;GAMG;AAEH,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,OAAO,GAAG,OAAO,CAAA;AAE5D,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,gBAAgB,CAAA;IACxB,KAAK,EAAE,OAAO,CAAA;IACd,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,6BAA6B;IAC7B,KAAK,EAAE,aAAa,GAAG,IAAI,CAAA;IAC3B,kEAAkE;IAClE,GAAG,EAAE,WAAW,GAAG,IAAI,CAAA;IACvB,6EAA6E;IAC7E,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAA;IAC/B,sFAAsF;IACtF,KAAK,EAAE,CAAC,OAAO,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;CAC5F;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IAC7F,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IAC3D,KAAK,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IAC5D,MAAM,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;CAC9C;AAED,MAAM,WAAW,oBAAoB;IACnC;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;CAC9B;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG,eAAe,CAkFjF"}
@@ -97,10 +97,19 @@ function useTanqoryApp(options = {}) {
97
97
  error,
98
98
  store,
99
99
  api,
100
- can: (scope) =>
101
- // `'*'` is the store-owner wildcard. Without this branch the one merchant
102
- // guaranteed to be allowed everything would see no actions at all.
103
- store?.permissions.includes('*') || store?.permissions.includes(scope) || false,
100
+ can: (scope) => {
101
+ if (!store)
102
+ return false;
103
+ // The host already intersects the merchant's permissions with the app's
104
+ // grant for a marketplace guest (app-bridge ≥0.7), so `permissions` is
105
+ // the right thing to check on either path. `grantedScopes`, when present,
106
+ // is the grant itself — a scope outside it is refused even for a store
107
+ // owner, whose `'*'` wildcard otherwise made this return true for every
108
+ // scope regardless of what was granted.
109
+ if (store.grantedScopes && !store.grantedScopes.includes(scope))
110
+ return false;
111
+ return store.permissions.includes('*') || store.permissions.includes(scope);
112
+ },
104
113
  toast: (variant, title, description) => bridgeRef.current?.post('TOAST', { variant, title, description }),
105
114
  };
106
115
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanqory/plugin-sdk",
3
- "version": "0.6.1",
3
+ "version": "0.6.3",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/tanqory/tanqory-platform-packages.git",
@@ -1,18 +0,0 @@
1
- /**
2
- * The JSON Schema and `parseAppManifest` must agree.
3
- *
4
- * `parseAppManifest` is hand-written on purpose — this package is installed by
5
- * strangers, and a schema library would be one more dependency they are asked to
6
- * trust. So the schema shipped for editors and agents cannot be derived from it;
7
- * it is written alongside, and would drift the moment anyone changed one and not
8
- * the other.
9
- *
10
- * This is what stops that. Every case runs through both, and the two must reach
11
- * the same verdict. A rule added to one and forgotten in the other fails here
12
- * rather than in someone's editor six weeks later, telling them a manifest is
13
- * fine that submission will reject.
14
- *
15
- * `ajv` is a devDependency. Nothing here ships.
16
- */
17
- export {};
18
- //# sourceMappingURL=manifest.schema.spec.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"manifest.schema.spec.d.ts","sourceRoot":"","sources":["../src/manifest.schema.spec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG"}
@@ -1,164 +0,0 @@
1
- "use strict";
2
- /**
3
- * The JSON Schema and `parseAppManifest` must agree.
4
- *
5
- * `parseAppManifest` is hand-written on purpose — this package is installed by
6
- * strangers, and a schema library would be one more dependency they are asked to
7
- * trust. So the schema shipped for editors and agents cannot be derived from it;
8
- * it is written alongside, and would drift the moment anyone changed one and not
9
- * the other.
10
- *
11
- * This is what stops that. Every case runs through both, and the two must reach
12
- * the same verdict. A rule added to one and forgotten in the other fails here
13
- * rather than in someone's editor six weeks later, telling them a manifest is
14
- * fine that submission will reject.
15
- *
16
- * `ajv` is a devDependency. Nothing here ships.
17
- */
18
- var __importDefault = (this && this.__importDefault) || function (mod) {
19
- return (mod && mod.__esModule) ? mod : { "default": mod };
20
- };
21
- Object.defineProperty(exports, "__esModule", { value: true });
22
- const node_fs_1 = require("node:fs");
23
- const node_path_1 = require("node:path");
24
- const ajv_1 = __importDefault(require("ajv"));
25
- const vitest_1 = require("vitest");
26
- const manifest_1 = require("./manifest");
27
- const schema = JSON.parse((0, node_fs_1.readFileSync)((0, node_path_1.join)(__dirname, '..', 'schema', 'tanqory-app.schema.json'), 'utf8'));
28
- const ajv = new ajv_1.default({ allErrors: true, strict: false });
29
- const validateWithSchema = ajv.compile(schema);
30
- const VALID = {
31
- handle: 'order-notifier',
32
- name: 'Order Notifier',
33
- appUrl: 'https://order-notifier.example.com',
34
- devUrl: 'http://localhost:3000',
35
- embedded: { enabled: true, path: '/embed' },
36
- scopes: ['orders.view'],
37
- webhooks: [{ topic: 'orders/create', path: '/hooks/orders' }],
38
- };
39
- /** What each side says about the same input. */
40
- function verdicts(manifest) {
41
- let validator = true;
42
- try {
43
- (0, manifest_1.parseAppManifest)(manifest);
44
- }
45
- catch {
46
- validator = false;
47
- }
48
- return { schema: validateWithSchema(manifest), validator };
49
- }
50
- const cases = [
51
- ['the scaffold default', VALID, true],
52
- ['no devUrl', { ...VALID, devUrl: undefined }, true],
53
- [
54
- 'a manifest with every optional field',
55
- {
56
- ...VALID,
57
- supportUrl: 'https://example.com/support',
58
- privacyPolicyUrl: 'https://example.com/privacy',
59
- appType: 'embed',
60
- navigation: { placement: 'orders', items: [{ label: 'Settings', path: '/embed/settings' }] },
61
- iframe: { minHeight: 600, width: 'full' },
62
- },
63
- true,
64
- ],
65
- [
66
- 'notification capability with a dispatchUrl',
67
- {
68
- ...VALID,
69
- provides: ['notification-channel:sms'],
70
- notifications: { dispatchUrl: 'https://example.com/dispatch' },
71
- },
72
- true,
73
- ],
74
- ['an uppercase handle', { ...VALID, handle: 'OrderNotifier' }, false],
75
- ['a handle with spaces', { ...VALID, handle: 'order notifier' }, false],
76
- ['a leading hyphen in the handle', { ...VALID, handle: '-order' }, false],
77
- ['no handle at all', { ...VALID, handle: undefined }, false],
78
- ['an empty name', { ...VALID, name: '' }, false],
79
- ['a plain http appUrl', { ...VALID, appUrl: 'http://example.com' }, false],
80
- [
81
- 'a devUrl on plain http that is not localhost',
82
- { ...VALID, devUrl: 'http://example.com' },
83
- false,
84
- ],
85
- ['scopes as a string', { ...VALID, scopes: 'orders.view' }, false],
86
- ['a duplicated scope', { ...VALID, scopes: ['orders.view', 'orders.view'] }, false],
87
- [
88
- 'an embedded.path with no leading slash',
89
- { ...VALID, embedded: { enabled: true, path: 'embed' } },
90
- false,
91
- ],
92
- ['embedded.enabled as a string', { ...VALID, embedded: { enabled: 'yes' } }, false],
93
- [
94
- 'a webhook path with no leading slash',
95
- { ...VALID, webhooks: [{ topic: 'orders/create', path: 'hooks' }] },
96
- false,
97
- ],
98
- ['a webhook with no topic', { ...VALID, webhooks: [{ path: '/hooks' }] }, false],
99
- ['appType outside the enum', { ...VALID, appType: 'popup' }, false],
100
- ['iframe.width outside the enum', { ...VALID, iframe: { width: 'wide' } }, false],
101
- ['a negative iframe.minHeight', { ...VALID, iframe: { minHeight: -1 } }, false],
102
- ['navigation with no placement', { ...VALID, navigation: { items: [] } }, false],
103
- [
104
- 'a navigation item with no label',
105
- { ...VALID, navigation: { placement: 'orders', items: [{ path: '/embed' }] } },
106
- false,
107
- ],
108
- // The field that never existed but shipped in an early first-party manifest.
109
- // Rejected by name so the fix is obvious rather than silently ignored.
110
- ['the legacy embeddedPath field', { ...VALID, embeddedPath: '/embed' }, false],
111
- // Taking over a notification with nowhere for it to go.
112
- [
113
- 'a notification capability with no dispatchUrl',
114
- { ...VALID, provides: ['notification-override:order_confirmation'] },
115
- false,
116
- ],
117
- [
118
- 'a dispatchUrl on localhost',
119
- {
120
- ...VALID,
121
- provides: ['notification-channel:sms'],
122
- notifications: { dispatchUrl: 'http://localhost:3000/dispatch' },
123
- },
124
- false,
125
- ],
126
- ];
127
- (0, vitest_1.describe)('the JSON Schema agrees with parseAppManifest', () => {
128
- vitest_1.it.each(cases)('%s', (_label, manifest, expected) => {
129
- const { schema: bySchema, validator: byValidator } = verdicts(manifest);
130
- // The assertion that matters is that they agree. Comparing both to the
131
- // expectation separately would let a case pass while the two disagreed
132
- // about why.
133
- (0, vitest_1.expect)({ schema: bySchema, validator: byValidator }).toEqual({
134
- schema: expected,
135
- validator: expected,
136
- });
137
- });
138
- (0, vitest_1.it)('lists every field the type declares, so a new one cannot be forgotten', () => {
139
- // `additionalProperties: false` means a field added to the type but not to
140
- // the schema is rejected by an editor while submission accepts it — the
141
- // drift that is hardest to spot, because the tool is wrong and the platform
142
- // is right.
143
- const declared = Object.keys(schema.properties).sort();
144
- (0, vitest_1.expect)(declared).toEqual([
145
- '$schema',
146
- 'appType',
147
- 'appUrl',
148
- 'devUrl',
149
- 'embedded',
150
- 'embeddedPath',
151
- 'handle',
152
- 'iframe',
153
- 'name',
154
- 'navigation',
155
- 'notifications',
156
- 'privacyPolicyUrl',
157
- 'provides',
158
- 'scopes',
159
- 'supportUrl',
160
- 'webhooks',
161
- ].sort());
162
- });
163
- });
164
- //# sourceMappingURL=manifest.schema.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"manifest.schema.spec.js","sourceRoot":"","sources":["../src/manifest.schema.spec.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=manifest.spec.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"manifest.spec.d.ts","sourceRoot":"","sources":["../src/manifest.spec.ts"],"names":[],"mappings":""}
@@ -1,193 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const vitest_1 = require("vitest");
4
- const manifest_1 = require("./manifest");
5
- const VALID = {
6
- handle: 'order-notifier',
7
- name: 'Order Notifier',
8
- appUrl: 'https://order-notifier.example.com',
9
- scopes: ['orders.view'],
10
- };
11
- /** Collect the problems without asserting on prose. */
12
- function problemsOf(input) {
13
- try {
14
- (0, manifest_1.parseAppManifest)(input);
15
- return [];
16
- }
17
- catch (error) {
18
- return error instanceof manifest_1.ManifestError ? error.problems : [String(error)];
19
- }
20
- }
21
- (0, vitest_1.describe)('parseAppManifest', () => {
22
- (0, vitest_1.it)('accepts a minimal manifest', () => {
23
- (0, vitest_1.expect)((0, manifest_1.parseAppManifest)(VALID)).toMatchObject({ handle: 'order-notifier' });
24
- });
25
- (0, vitest_1.it)('reports every problem at once, not just the first', () => {
26
- // A validator that stops at the first error turns a five-field mistake into
27
- // five round trips — and this is the first thing a new developer runs.
28
- const problems = problemsOf({ handle: 'Not Valid', appUrl: 'ftp://x', scopes: 'nope' });
29
- (0, vitest_1.expect)(problems.length).toBeGreaterThanOrEqual(4);
30
- });
31
- (0, vitest_1.describe)('handle', () => {
32
- vitest_1.it.each([
33
- ['uppercase', 'OrderNotifier'],
34
- ['spaces', 'order notifier'],
35
- ['leading hyphen', '-order'],
36
- ['double hyphen', 'order--notifier'],
37
- ['empty', ''],
38
- ])('rejects %s', (_label, handle) => {
39
- (0, vitest_1.expect)(problemsOf({ ...VALID, handle })).not.toEqual([]);
40
- });
41
- });
42
- (0, vitest_1.describe)('urls', () => {
43
- (0, vitest_1.it)('requires https for appUrl', () => {
44
- (0, vitest_1.expect)(problemsOf({ ...VALID, appUrl: 'http://example.com' })).not.toEqual([]);
45
- });
46
- (0, vitest_1.it)('allows http on localhost for devUrl only', () => {
47
- // A merchant is never sent to devUrl, and demanding TLS on a laptop is
48
- // friction with no payoff.
49
- (0, vitest_1.expect)(problemsOf({ ...VALID, devUrl: 'http://localhost:3000' })).toEqual([]);
50
- (0, vitest_1.expect)(problemsOf({ ...VALID, devUrl: 'http://evil.example.com' })).not.toEqual([]);
51
- });
52
- });
53
- (0, vitest_1.describe)('scopes', () => {
54
- (0, vitest_1.it)('rejects a duplicate', () => {
55
- // Silently de-duplicating would make the consent screen and the manifest
56
- // disagree about what was asked for.
57
- (0, vitest_1.expect)(problemsOf({ ...VALID, scopes: ['orders.view', 'orders.view'] })).not.toEqual([]);
58
- });
59
- (0, vitest_1.it)('accepts an empty list', () => {
60
- // An app that only renders UI needs no scopes, and forcing one would push
61
- // developers to request something they do not use.
62
- (0, vitest_1.expect)(problemsOf({ ...VALID, scopes: [] })).toEqual([]);
63
- });
64
- });
65
- (0, vitest_1.describe)('webhooks', () => {
66
- (0, vitest_1.it)('requires a topic and a rooted path', () => {
67
- (0, vitest_1.expect)(problemsOf({ ...VALID, webhooks: [{ topic: '', path: 'no-slash' }] }).length).toBe(2);
68
- });
69
- (0, vitest_1.it)('accepts a well-formed subscription', () => {
70
- (0, vitest_1.expect)(problemsOf({ ...VALID, webhooks: [{ topic: 'orders/create', path: '/hooks/orders' }] })).toEqual([]);
71
- });
72
- });
73
- (0, vitest_1.it)('requires embedded.path to be rooted when present', () => {
74
- (0, vitest_1.expect)(problemsOf({ ...VALID, embedded: { enabled: true, path: 'embed' } })).not.toEqual([]);
75
- (0, vitest_1.expect)(problemsOf({ ...VALID, embedded: { enabled: true, path: '/embed' } })).toEqual([]);
76
- });
77
- (0, vitest_1.it)('does not throw on null or a non-object', () => {
78
- (0, vitest_1.expect)(problemsOf(null)).not.toEqual([]);
79
- (0, vitest_1.expect)(problemsOf('a string')).not.toEqual([]);
80
- });
81
- (0, vitest_1.describe)('manifest v2 — surface declaration', () => {
82
- (0, vitest_1.it)('accepts a full v2 manifest', () => {
83
- (0, vitest_1.expect)(problemsOf({
84
- ...VALID,
85
- appType: 'embed',
86
- navigation: {
87
- placement: 'marketing',
88
- items: [
89
- { label: 'Campaigns', path: '/campaigns' },
90
- { label: 'Automations', path: '/automations' },
91
- ],
92
- },
93
- iframe: { minHeight: 480, width: 'full' },
94
- provides: ['marketing-suite'],
95
- })).toEqual([]);
96
- });
97
- (0, vitest_1.it)('a v1 manifest with none of the new fields stays valid unchanged', () => {
98
- (0, vitest_1.expect)(problemsOf(VALID)).toEqual([]);
99
- });
100
- (0, vitest_1.it)('rejects the legacy top-level embeddedPath by name', () => {
101
- const problems = problemsOf({ ...VALID, embeddedPath: '/embed' });
102
- (0, vitest_1.expect)(problems.join(' ')).toContain('embeddedPath');
103
- (0, vitest_1.expect)(problems.join(' ')).toContain('embedded: { enabled: true');
104
- });
105
- (0, vitest_1.it)('rejects an unknown appType', () => {
106
- (0, vitest_1.expect)(problemsOf({ ...VALID, appType: 'popup' })).not.toEqual([]);
107
- });
108
- (0, vitest_1.it)('navigation.placement must be a slug; membership is enforced at review, not here', () => {
109
- (0, vitest_1.expect)(problemsOf({ ...VALID, navigation: { placement: 'Not A Slug' } })).not.toEqual([]);
110
- // Shape-valid but not a known slot today — the SDK passes it so a new
111
- // platform slot never requires an SDK release; review owns the list.
112
- (0, vitest_1.expect)(problemsOf({ ...VALID, navigation: { placement: 'future_slot' } })).toEqual([]);
113
- });
114
- (0, vitest_1.it)('navigation items need a label and a rooted, traversal-free path', () => {
115
- const problems = problemsOf({
116
- ...VALID,
117
- navigation: { placement: 'marketing', items: [{ label: '', path: '/a/../b' }] },
118
- });
119
- (0, vitest_1.expect)(problems.length).toBe(2);
120
- });
121
- (0, vitest_1.it)('iframe constraints: positive minHeight, width from the pair', () => {
122
- (0, vitest_1.expect)(problemsOf({ ...VALID, iframe: { minHeight: -1 } })).not.toEqual([]);
123
- (0, vitest_1.expect)(problemsOf({ ...VALID, iframe: { width: 'wide' } })).not.toEqual([]);
124
- (0, vitest_1.expect)(problemsOf({ ...VALID, iframe: { minHeight: 320, width: 'centered' } })).toEqual([]);
125
- });
126
- (0, vitest_1.it)('provides entries are slugs, no duplicates', () => {
127
- (0, vitest_1.expect)(problemsOf({ ...VALID, provides: ['Marketing Suite'] })).not.toEqual([]);
128
- (0, vitest_1.expect)(problemsOf({ ...VALID, provides: ['marketing-suite', 'marketing-suite'] })).not.toEqual([]);
129
- (0, vitest_1.expect)(problemsOf({ ...VALID, provides: ['marketing-suite'] })).toEqual([]);
130
- });
131
- });
132
- (0, vitest_1.describe)('notification capabilities', () => {
133
- const NOTIFY = { dispatchUrl: 'https://hooks.example.com/tanqory/notifications' };
134
- (0, vitest_1.it)('accepts an override and a channel alongside a plain capability', () => {
135
- (0, vitest_1.expect)(problemsOf({
136
- ...VALID,
137
- provides: [
138
- 'marketing-suite',
139
- 'notification-override:order_new',
140
- 'notification-channel:line',
141
- ],
142
- notifications: NOTIFY,
143
- })).toEqual([]);
144
- });
145
- (0, vitest_1.it)('passes an unknown type or channel name — that vocabulary is the platform’s', () => {
146
- // Shape-valid but not in today's registry. The SDK lets it through for
147
- // the same reason it lets an unknown nav placement through: the list
148
- // lives server-side and must grow without an SDK release.
149
- (0, vitest_1.expect)(problemsOf({
150
- ...VALID,
151
- provides: ['notification-override:some_future_type'],
152
- notifications: NOTIFY,
153
- })).toEqual([]);
154
- });
155
- (0, vitest_1.it)('rejects an unknown capability family', () => {
156
- const problems = problemsOf({
157
- ...VALID,
158
- provides: ['notification-takeover:order_new'],
159
- notifications: NOTIFY,
160
- });
161
- (0, vitest_1.expect)(problems.join(' ')).toContain('notification-takeover');
162
- (0, vitest_1.expect)(problems.join(' ')).toContain('notification-override:<name>');
163
- });
164
- vitest_1.it.each([
165
- ['an empty name', 'notification-override:'],
166
- ['an uppercase name', 'notification-channel:LINE'],
167
- ['a spaced name', 'notification-override:order new'],
168
- ['a second colon', 'notification-override:order:new'],
169
- ])('rejects %s', (_label, capability) => {
170
- (0, vitest_1.expect)(problemsOf({ ...VALID, provides: [capability], notifications: NOTIFY })).not.toEqual([]);
171
- });
172
- (0, vitest_1.it)('requires a dispatchUrl once a notification capability is declared', () => {
173
- // A takeover with nowhere to deliver drops every message it claimed —
174
- // the one failure mode a merchant would never see in the UI.
175
- const problems = problemsOf({ ...VALID, provides: ['notification-override:order_new'] });
176
- (0, vitest_1.expect)(problems.join(' ')).toContain('notifications.dispatchUrl');
177
- });
178
- (0, vitest_1.it)('does not require a dispatchUrl for a plain capability', () => {
179
- (0, vitest_1.expect)(problemsOf({ ...VALID, provides: ['marketing-suite'] })).toEqual([]);
180
- });
181
- vitest_1.it.each([
182
- ['http', 'http://hooks.example.com/n'],
183
- ['localhost', 'https://localhost:3000/n'],
184
- ['a loopback ip', 'https://127.0.0.1/n'],
185
- ['not a URL at all', '/notifications'],
186
- ])('rejects a dispatchUrl on %s', (_label, dispatchUrl) => {
187
- // Unlike `devUrl`, this URL is called BY Tanqory. A laptop address here
188
- // is one nothing can ever reach, so it is refused rather than tolerated.
189
- (0, vitest_1.expect)(problemsOf({ ...VALID, notifications: { dispatchUrl } })).not.toEqual([]);
190
- });
191
- });
192
- });
193
- //# sourceMappingURL=manifest.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"manifest.spec.js","sourceRoot":"","sources":["../src/manifest.spec.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=webhooks.spec.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"webhooks.spec.d.ts","sourceRoot":"","sources":["../src/webhooks.spec.ts"],"names":[],"mappings":""}
@@ -1,74 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const node_crypto_1 = require("node:crypto");
4
- const vitest_1 = require("vitest");
5
- const webhooks_1 = require("./webhooks");
6
- /**
7
- * This function is the only thing standing between an app's webhook handler and
8
- * anyone on the internet who knows its URL. Every case below is a way that
9
- * boundary gets crossed by an implementation that "looks right".
10
- */
11
- const SECRET = 'whsec_test';
12
- const BODY = '{"event":"orders/create","data":{"id":"ord_1"}}';
13
- function sign(body, timestamp, secret = SECRET) {
14
- const signature = (0, node_crypto_1.createHmac)('sha256', secret).update(`${timestamp}.${body}`).digest('hex');
15
- return `t=${timestamp},v1=${signature}`;
16
- }
17
- const NOW = 1_700_000_000_000;
18
- const now = () => NOW;
19
- const nowSeconds = Math.floor(NOW / 1000);
20
- (0, vitest_1.describe)('verifyWebhookSignature', () => {
21
- (0, vitest_1.it)('accepts a correctly signed, fresh payload', () => {
22
- (0, vitest_1.expect)((0, webhooks_1.verifyWebhookSignature)(BODY, sign(BODY, nowSeconds), SECRET, { now })).toBe(true);
23
- });
24
- (0, vitest_1.it)('rejects a body that changed after signing', () => {
25
- const header = sign(BODY, nowSeconds);
26
- const tampered = BODY.replace('ord_1', 'ord_999');
27
- (0, vitest_1.expect)((0, webhooks_1.verifyWebhookSignature)(tampered, header, SECRET, { now })).toBe(false);
28
- });
29
- (0, vitest_1.it)('rejects a signature made with a different secret', () => {
30
- const header = sign(BODY, nowSeconds, 'whsec_someone_elses');
31
- (0, vitest_1.expect)((0, webhooks_1.verifyWebhookSignature)(BODY, header, SECRET, { now })).toBe(false);
32
- });
33
- (0, vitest_1.describe)('replay', () => {
34
- (0, vitest_1.it)('rejects a payload older than the tolerance', () => {
35
- // Without this, a captured delivery verifies forever.
36
- const header = sign(BODY, nowSeconds - 301);
37
- (0, vitest_1.expect)((0, webhooks_1.verifyWebhookSignature)(BODY, header, SECRET, { now })).toBe(false);
38
- });
39
- (0, vitest_1.it)('accepts one just inside the tolerance', () => {
40
- const header = sign(BODY, nowSeconds - 299);
41
- (0, vitest_1.expect)((0, webhooks_1.verifyWebhookSignature)(BODY, header, SECRET, { now })).toBe(true);
42
- });
43
- (0, vitest_1.it)('rejects a timestamp in the future', () => {
44
- // Not a clock problem to be generous about — a future timestamp means
45
- // someone chose it.
46
- const header = sign(BODY, nowSeconds + 301);
47
- (0, vitest_1.expect)((0, webhooks_1.verifyWebhookSignature)(BODY, header, SECRET, { now })).toBe(false);
48
- });
49
- });
50
- (0, vitest_1.describe)('malformed input is rejected, never thrown on', () => {
51
- // A handler that 500s on a malformed header tells an attacker their probe
52
- // reached real code. Every one of these must simply be false.
53
- const bad = [
54
- ['missing header', null],
55
- ['empty header', ''],
56
- ['no timestamp', 'v1=abc'],
57
- ['no signature', `t=${nowSeconds}`],
58
- ['non-numeric timestamp', 't=not-a-number,v1=abc'],
59
- ['garbage', 'nonsense'],
60
- ];
61
- vitest_1.it.each(bad)('rejects %s', (_label, header) => {
62
- (0, vitest_1.expect)((0, webhooks_1.verifyWebhookSignature)(BODY, header, SECRET, { now })).toBe(false);
63
- });
64
- (0, vitest_1.it)('rejects when no secret is configured', () => {
65
- (0, vitest_1.expect)((0, webhooks_1.verifyWebhookSignature)(BODY, sign(BODY, nowSeconds), '', { now })).toBe(false);
66
- });
67
- });
68
- (0, vitest_1.it)('rejects a signature of the right shape but the wrong length', () => {
69
- // Guards the constant-time compare: a length mismatch must return false,
70
- // not throw, or the throw itself becomes the timing signal.
71
- (0, vitest_1.expect)((0, webhooks_1.verifyWebhookSignature)(BODY, `t=${nowSeconds},v1=abc`, SECRET, { now })).toBe(false);
72
- });
73
- });
74
- //# sourceMappingURL=webhooks.spec.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"webhooks.spec.js","sourceRoot":"","sources":["../src/webhooks.spec.ts"],"names":[],"mappings":";;AAAA,6CAAwC;AAExC,mCAA6C;AAE7C,yCAAmD;AAEnD;;;;GAIG;AAEH,MAAM,MAAM,GAAG,YAAY,CAAA;AAC3B,MAAM,IAAI,GAAG,iDAAiD,CAAA;AAE9D,SAAS,IAAI,CAAC,IAAY,EAAE,SAAiB,EAAE,MAAM,GAAG,MAAM;IAC5D,MAAM,SAAS,GAAG,IAAA,wBAAU,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,GAAG,SAAS,IAAI,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IAC3F,OAAO,KAAK,SAAS,OAAO,SAAS,EAAE,CAAA;AACzC,CAAC;AAED,MAAM,GAAG,GAAG,iBAAiB,CAAA;AAC7B,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC,GAAG,CAAA;AACrB,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC,CAAA;AAEzC,IAAA,iBAAQ,EAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,IAAA,WAAE,EAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,IAAA,eAAM,EAAC,IAAA,iCAAsB,EAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC1F,CAAC,CAAC,CAAA;IAEF,IAAA,WAAE,EAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;QACjD,IAAA,eAAM,EAAC,IAAA,iCAAsB,EAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC/E,CAAC,CAAC,CAAA;IAEF,IAAA,WAAE,EAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,qBAAqB,CAAC,CAAA;QAC5D,IAAA,eAAM,EAAC,IAAA,iCAAsB,EAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC3E,CAAC,CAAC,CAAA;IAEF,IAAA,iBAAQ,EAAC,QAAQ,EAAE,GAAG,EAAE;QACtB,IAAA,WAAE,EAAC,4CAA4C,EAAE,GAAG,EAAE;YACpD,sDAAsD;YACtD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,GAAG,CAAC,CAAA;YAC3C,IAAA,eAAM,EAAC,IAAA,iCAAsB,EAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC3E,CAAC,CAAC,CAAA;QAEF,IAAA,WAAE,EAAC,uCAAuC,EAAE,GAAG,EAAE;YAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,GAAG,CAAC,CAAA;YAC3C,IAAA,eAAM,EAAC,IAAA,iCAAsB,EAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAC1E,CAAC,CAAC,CAAA;QAEF,IAAA,WAAE,EAAC,mCAAmC,EAAE,GAAG,EAAE;YAC3C,sEAAsE;YACtE,oBAAoB;YACpB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,GAAG,CAAC,CAAA;YAC3C,IAAA,eAAM,EAAC,IAAA,iCAAsB,EAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC3E,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,IAAA,iBAAQ,EAAC,8CAA8C,EAAE,GAAG,EAAE;QAC5D,0EAA0E;QAC1E,8DAA8D;QAC9D,MAAM,GAAG,GAAG;YACV,CAAC,gBAAgB,EAAE,IAAI,CAAC;YACxB,CAAC,cAAc,EAAE,EAAE,CAAC;YACpB,CAAC,cAAc,EAAE,QAAQ,CAAC;YAC1B,CAAC,cAAc,EAAE,KAAK,UAAU,EAAE,CAAC;YACnC,CAAC,uBAAuB,EAAE,uBAAuB,CAAC;YAClD,CAAC,SAAS,EAAE,UAAU,CAAC;SACf,CAAA;QAEV,WAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE;YAC5C,IAAA,eAAM,EAAC,IAAA,iCAAsB,EAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC3E,CAAC,CAAC,CAAA;QAEF,IAAA,WAAE,EAAC,sCAAsC,EAAE,GAAG,EAAE;YAC9C,IAAA,eAAM,EAAC,IAAA,iCAAsB,EAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACvF,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,IAAA,WAAE,EAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,yEAAyE;QACzE,4DAA4D;QAC5D,IAAA,eAAM,EAAC,IAAA,iCAAsB,EAAC,IAAI,EAAE,KAAK,UAAU,SAAS,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC7F,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}