@oxygen-agent/cli 1.893.0 → 1.894.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.
package/README.md CHANGED
@@ -34,4 +34,4 @@ oxygen update
34
34
 
35
35
  For product documentation, visit https://oxygen-agent.com/docs. For support, visit https://oxygen-agent.com.
36
36
 
37
- Version: 1.893.0
37
+ Version: 1.894.0
@@ -96,12 +96,35 @@ export declare const SENDING_SEAT_GATE_ENABLED_ENV_VAR = "OXYGEN_SENDING_SEAT_GA
96
96
  /**
97
97
  * Which seat kind a connect request consumes, by CLI path prefix.
98
98
  *
99
- * MAILBOXES ARE DELIBERATELY ABSENT. Email mailboxes live in the TENANT
100
- * database, so the control-plane grandfathering backfill cannot see them and did
101
- * not cover them. Enforcing a seat on mailbox connect today would refuse
102
- * customers who already have mailboxes attached — the precise failure this whole
103
- * grandfathering design exists to prevent. Add mailboxes here only once a
104
- * tenant-aware backfill has granted their legacy entitlements.
99
+ * ALL FOUR CHANNELS are mapped. Mailboxes were held back while grandfathering
100
+ * was backfill-only, because the backfill runs in the control plane and mailboxes
101
+ * live in each tenant's own database — gating them then would have refused
102
+ * customers who already had mailboxes attached. They are safe to include now
103
+ * that the gate grandfathers an organization's existing senders on FIRST CONTACT
104
+ * (see ensureLegacyEntitlementOnFirstContact), which needs no cross-tenant sweep
105
+ * and cannot miss a tenant.
105
106
  */
106
- export declare const SEAT_KIND_BY_CONNECT_PREFIX: ReadonlyArray<readonly [prefix: string, seatKey: SendingSeatKey]>;
107
- export declare function seatKindForConnectPath(pathname: string): SendingSeatKey | null;
107
+ export type SeatConnectRoute = {
108
+ readonly path: string;
109
+ readonly seatKey: SendingSeatKey;
110
+ /**
111
+ * `prefix` also matches sub-paths, for flows that continue under the same
112
+ * route (an OAuth callback). `exact` matches only the route itself.
113
+ *
114
+ * The distinction is load-bearing. `/api/cli/voice/numbers` buys a number, but
115
+ * `/api/cli/voice/numbers/<id>` and `/<id>/tags` manage an EXISTING one — and
116
+ * gating those would refuse a customer at capacity from RELEASING a number,
117
+ * which is the one action that frees capacity. Prefix-matching everything was
118
+ * the first version of this and it had exactly that bug.
119
+ */
120
+ readonly match: "exact" | "prefix";
121
+ };
122
+ export declare const SEAT_CONNECT_ROUTES: readonly SeatConnectRoute[];
123
+ /**
124
+ * Which seat a request consumes, or null.
125
+ *
126
+ * METHOD MATTERS: only a request that CREATES a sender consumes capacity.
127
+ * `GET /api/cli/voice/numbers` lists what you already own and must never be
128
+ * refused for want of a seat.
129
+ */
130
+ export declare function seatKindForConnect(pathname: string, method: string): SendingSeatKey | null;
@@ -137,24 +137,28 @@ export function sendingSeatGateEnabled(env = process.env) {
137
137
  return normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on";
138
138
  }
139
139
  export const SENDING_SEAT_GATE_ENABLED_ENV_VAR = "OXYGEN_SENDING_SEAT_GATE_ENABLED";
140
+ export const SEAT_CONNECT_ROUTES = [
141
+ { path: "/api/cli/senders/connect", seatKey: "linkedin", match: "prefix" },
142
+ { path: "/api/cli/whatsapp/connect", seatKey: "whatsapp", match: "prefix" },
143
+ { path: "/api/cli/mailboxes/connect-oauth", seatKey: "email_sender", match: "prefix" },
144
+ { path: "/api/cli/voice/numbers", seatKey: "phone_number", match: "exact" },
145
+ ];
140
146
  /**
141
- * Which seat kind a connect request consumes, by CLI path prefix.
147
+ * Which seat a request consumes, or null.
142
148
  *
143
- * MAILBOXES ARE DELIBERATELY ABSENT. Email mailboxes live in the TENANT
144
- * database, so the control-plane grandfathering backfill cannot see them and did
145
- * not cover them. Enforcing a seat on mailbox connect today would refuse
146
- * customers who already have mailboxes attached — the precise failure this whole
147
- * grandfathering design exists to prevent. Add mailboxes here only once a
148
- * tenant-aware backfill has granted their legacy entitlements.
149
+ * METHOD MATTERS: only a request that CREATES a sender consumes capacity.
150
+ * `GET /api/cli/voice/numbers` lists what you already own and must never be
151
+ * refused for want of a seat.
149
152
  */
150
- export const SEAT_KIND_BY_CONNECT_PREFIX = [
151
- ["/api/cli/senders/connect", "linkedin"],
152
- ["/api/cli/whatsapp/connect", "whatsapp"],
153
- ];
154
- export function seatKindForConnectPath(pathname) {
155
- for (const [prefix, seatKey] of SEAT_KIND_BY_CONNECT_PREFIX) {
156
- if (pathname === prefix || pathname.startsWith(`${prefix}/`))
157
- return seatKey;
153
+ export function seatKindForConnect(pathname, method) {
154
+ if (method.toUpperCase() !== "POST")
155
+ return null;
156
+ for (const route of SEAT_CONNECT_ROUTES) {
157
+ const hit = route.match === "exact"
158
+ ? pathname === route.path
159
+ : pathname === route.path || pathname.startsWith(`${route.path}/`);
160
+ if (hit)
161
+ return route.seatKey;
158
162
  }
159
163
  return null;
160
164
  }
@@ -1,4 +1,4 @@
1
- export declare const OXYGEN_VERSION = "1.893.0";
1
+ export declare const OXYGEN_VERSION = "1.894.0";
2
2
  export declare const OXYGEN_MINIMUM_CLI_VERSION = "1.181.0";
3
3
  export declare const MANAGED_INBOX_MINIMUM_CLI_VERSION = "1.326.2";
4
4
  export declare const SUPPORT_AGENT_REPLY_MINIMUM_CLI_VERSION = "1.747.0";
@@ -1,4 +1,4 @@
1
- export const OXYGEN_VERSION = "1.893.0";
1
+ export const OXYGEN_VERSION = "1.894.0";
2
2
  // The GLOBAL CLI compatibility floor: the oldest CLI allowed to call any
3
3
  // operational route. Raising it hard-rejects every older CLI from the entire
4
4
  // product, so it obeys one law, enforced by scripts/ci/cli-min-version-gate.mjs:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxygen-agent/cli",
3
- "version": "1.893.0",
3
+ "version": "1.894.0",
4
4
  "private": false,
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",