@hostwebhook/platform-node 0.4.0 → 0.5.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.
@@ -66,8 +66,39 @@ export declare const SHOPIFY_CREDENTIAL_TYPE = "shopify_oauth2";
66
66
  *
67
67
  * `read_all_orders` is deliberately absent: it needs a separate approval from
68
68
  * Shopify and only widens the window past 60 days, which nothing in v1 uses.
69
+ *
70
+ * ## 🔑 [2026-09-08] Three added, and they cost a reconnect
71
+ *
72
+ * The action node grew six operations, and three of them need permissions the
73
+ * app never asked for. Two things follow, and both are the kind that are
74
+ * discovered at the worst moment if they are not written down:
75
+ *
76
+ * 1. **Declaring them here is half the edit.** The other half is releasing a
77
+ * new version of the app in the Dev Dashboard with the same list. Until
78
+ * that is done Shopify refuses the AUTHORIZE step — so the symptom is not a
79
+ * failing node, it is a connection flow that will not start.
80
+ *
81
+ * 2. **Scopes are granted at install time.** Every credential connected before
82
+ * this list changed keeps the eight it was granted. It goes on working for
83
+ * the operations it already covered, and answers HTTP 403 on the three new
84
+ * ones until somebody presses Reconnect on it. That is why
85
+ * `SHOPIFY_OPERATION_SCOPES` exists in node-types: so the node can say
86
+ * which scope is missing instead of relaying a 403.
87
+ *
88
+ * `write_assigned_fulfillment_orders` is deliberately absent, and it is the
89
+ * one an over-eager list would include. It is for apps that ARE a fulfilment
90
+ * service — Shopify assigns them the fulfilment orders. HostWebhook is an
91
+ * order-management app: it fulfils what the merchant's own locations
92
+ * (`merchant_managed`) or their 3PL (`third_party`) hold. Asking for a
93
+ * permission the app has no use for is what makes a merchant read the install
94
+ * screen twice.
95
+ *
96
+ * Read scopes for the same resources are not listed either: on Shopify a write
97
+ * scope includes read, so `write_draft_orders` already grants
98
+ * `read_draft_orders`. (The eight above predate that being written down here
99
+ * and keep both spellings; they are harmless, just redundant.)
69
100
  */
70
- export declare const SHOPIFY_DEFAULT_SCOPES: readonly ["read_orders", "write_orders", "read_customers", "write_customers", "read_products", "write_products", "read_inventory", "write_inventory"];
101
+ export declare const SHOPIFY_DEFAULT_SCOPES: readonly ["read_orders", "write_orders", "read_customers", "write_customers", "read_products", "write_products", "read_inventory", "write_inventory", "write_draft_orders", "write_merchant_managed_fulfillment_orders", "write_third_party_fulfillment_orders"];
71
102
  /**
72
103
  * Shopify's own pattern for a store domain, anchored at both ends.
73
104
  *
@@ -75,6 +75,37 @@ exports.SHOPIFY_CREDENTIAL_TYPE = 'shopify_oauth2';
75
75
  *
76
76
  * `read_all_orders` is deliberately absent: it needs a separate approval from
77
77
  * Shopify and only widens the window past 60 days, which nothing in v1 uses.
78
+ *
79
+ * ## 🔑 [2026-09-08] Three added, and they cost a reconnect
80
+ *
81
+ * The action node grew six operations, and three of them need permissions the
82
+ * app never asked for. Two things follow, and both are the kind that are
83
+ * discovered at the worst moment if they are not written down:
84
+ *
85
+ * 1. **Declaring them here is half the edit.** The other half is releasing a
86
+ * new version of the app in the Dev Dashboard with the same list. Until
87
+ * that is done Shopify refuses the AUTHORIZE step — so the symptom is not a
88
+ * failing node, it is a connection flow that will not start.
89
+ *
90
+ * 2. **Scopes are granted at install time.** Every credential connected before
91
+ * this list changed keeps the eight it was granted. It goes on working for
92
+ * the operations it already covered, and answers HTTP 403 on the three new
93
+ * ones until somebody presses Reconnect on it. That is why
94
+ * `SHOPIFY_OPERATION_SCOPES` exists in node-types: so the node can say
95
+ * which scope is missing instead of relaying a 403.
96
+ *
97
+ * `write_assigned_fulfillment_orders` is deliberately absent, and it is the
98
+ * one an over-eager list would include. It is for apps that ARE a fulfilment
99
+ * service — Shopify assigns them the fulfilment orders. HostWebhook is an
100
+ * order-management app: it fulfils what the merchant's own locations
101
+ * (`merchant_managed`) or their 3PL (`third_party`) hold. Asking for a
102
+ * permission the app has no use for is what makes a merchant read the install
103
+ * screen twice.
104
+ *
105
+ * Read scopes for the same resources are not listed either: on Shopify a write
106
+ * scope includes read, so `write_draft_orders` already grants
107
+ * `read_draft_orders`. (The eight above predate that being written down here
108
+ * and keep both spellings; they are harmless, just redundant.)
78
109
  */
79
110
  exports.SHOPIFY_DEFAULT_SCOPES = [
80
111
  'read_orders',
@@ -85,6 +116,9 @@ exports.SHOPIFY_DEFAULT_SCOPES = [
85
116
  'write_products',
86
117
  'read_inventory',
87
118
  'write_inventory',
119
+ 'write_draft_orders',
120
+ 'write_merchant_managed_fulfillment_orders',
121
+ 'write_third_party_fulfillment_orders',
88
122
  ];
89
123
  /**
90
124
  * Shopify's own pattern for a store domain, anchored at both ends.
@@ -19,7 +19,7 @@ import { type RateLimitResult } from './un-hueco-se-toma-de-una-vez';
19
19
  export type { RateLimitResult };
20
20
  export declare function checkRateLimit(redis: Redis, webhookId: string, limitPerMinute: number): Promise<RateLimitResult>;
21
21
  export declare function checkChatRateLimit(redis: Redis, chatTriggerId: string, scopeKey: string, limitPerMinute: number): Promise<RateLimitResult>;
22
- export declare function checkOAuthRateLimit(redis: Redis, userId: string, provider: 'google' | 'mcp' | 'atlassian' | 'slack' | 'twitter' | 'mastodon' | 'linkedin' | 'mailchimp' | 'shopify' | 'notion' | 'github' | 'threads' | 'instagram' | 'facebook' | 'discord', limitPerHour: number): Promise<RateLimitResult>;
22
+ export declare function checkOAuthRateLimit(redis: Redis, userId: string, provider: 'google' | 'mcp' | 'atlassian' | 'slack' | 'twitter' | 'mastodon' | 'linkedin' | 'mailchimp' | 'shopify' | 'notion' | 'github' | 'calendly' | 'airtable' | 'threads' | 'instagram' | 'facebook' | 'discord', limitPerHour: number): Promise<RateLimitResult>;
23
23
  export declare function checkFlowLinkRateLimit(redis: Redis, organizationId: string, limitPerMinute: number): Promise<RateLimitResult>;
24
24
  /** Rate-limit incoming webhook requests at the ingress level. */
25
25
  export declare function checkIngressRateLimit(redis: Redis, webhookId: string, limitPerMinute: number): Promise<RateLimitResult>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hostwebhook/platform-node",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Lo que los servicios de HostWebhook comparten del lado de NODE: cifrado y utilidades que no pueden estar escritas dos veces",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",