@pellux/goodvibes-sdk 0.25.14 → 0.25.15

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.
@@ -3,7 +3,7 @@
3
3
  "product": {
4
4
  "id": "goodvibes",
5
5
  "surface": "operator",
6
- "version": "0.25.14"
6
+ "version": "0.25.15"
7
7
  },
8
8
  "auth": {
9
9
  "modes": [
@@ -1,6 +1,6 @@
1
1
  export declare const FOUNDATION_METADATA: {
2
2
  readonly productId: "goodvibes";
3
- readonly productVersion: "0.25.14";
3
+ readonly productVersion: "0.25.15";
4
4
  readonly operatorMethodCount: 224;
5
5
  readonly operatorEventCount: 30;
6
6
  readonly peerEndpointCount: 6;
@@ -1,7 +1,7 @@
1
1
  // Synced from packages/contracts/src/generated/foundation-metadata.ts
2
2
  export const FOUNDATION_METADATA = {
3
3
  "productId": "goodvibes",
4
- "productVersion": "0.25.14",
4
+ "productVersion": "0.25.15",
5
5
  "operatorMethodCount": 224,
6
6
  "operatorEventCount": 30,
7
7
  "peerEndpointCount": 6
@@ -3,7 +3,7 @@ export const OPERATOR_CONTRACT = {
3
3
  "product": {
4
4
  "id": "goodvibes",
5
5
  "surface": "operator",
6
- "version": "0.25.14"
6
+ "version": "0.25.15"
7
7
  },
8
8
  "auth": {
9
9
  "modes": [
@@ -21,7 +21,7 @@ export declare class CloudflareControlPlaneManager {
21
21
  private resolveSecretRef;
22
22
  private storeSecret;
23
23
  private requireUserTokens;
24
- private collectPermissionGroups;
24
+ private resolvePermissionGroupIds;
25
25
  private createProvisioningContext;
26
26
  private fetchWorker;
27
27
  private generateToken;
@@ -1 +1 @@
1
- {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/cloudflare/manager.ts"],"names":[],"mappings":"AAuCA,OAAO,KAAK,EAIV,6BAA6B,EAC7B,4BAA4B,EAC5B,uBAAuB,EACvB,wBAAwB,EACxB,sBAAsB,EACtB,uBAAuB,EAGvB,+BAA+B,EAC/B,gCAAgC,EAEhC,wBAAwB,EACxB,yBAAyB,EAMzB,gCAAgC,EAChC,iCAAiC,EAEjC,uBAAuB,EACvB,wBAAwB,EACxB,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,YAAY,CAAC;AAiBpB,qBAAa,6BAA6B;IAI5B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqD;IAClF,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;gBAEZ,OAAO,EAAE,6BAA6B;IAK7D,cAAc,IAAI,OAAO,CAAC,4BAA4B,CAAC;IA0C7D,iBAAiB,CAAC,KAAK,GAAE,gCAAqC,GAAG,iCAAiC;IAkB5F,sBAAsB,CAAC,KAAK,EAAE,+BAA+B,GAAG,OAAO,CAAC,gCAAgC,CAAC;IA0EzG,QAAQ,CAAC,KAAK,GAAE,uBAA4B,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAuEhF,QAAQ,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAuB3E,SAAS,CAAC,KAAK,EAAE,wBAAwB,GAAG,OAAO,CAAC,yBAAyB,CAAC;IA2S9E,MAAM,CAAC,KAAK,GAAE,qBAA0B,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAe1E,OAAO,CAAC,KAAK,GAAE,sBAA2B,GAAG,OAAO,CAAC,uBAAuB,CAAC;IA0BnF,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAC,iBAAiB;YAYX,eAAe;YAaf,oBAAoB;YAapB,wBAAwB;YAaxB,gBAAgB;YAahB,WAAW;IAOzB,OAAO,CAAC,iBAAiB;YAOX,uBAAuB;IAKrC,OAAO,CAAC,yBAAyB;YAQnB,WAAW;IAazB,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,SAAS;CAMlB"}
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/cloudflare/manager.ts"],"names":[],"mappings":"AAuCA,OAAO,KAAK,EAIV,6BAA6B,EAC7B,4BAA4B,EAC5B,uBAAuB,EACvB,wBAAwB,EACxB,sBAAsB,EACtB,uBAAuB,EAGvB,+BAA+B,EAC/B,gCAAgC,EAChC,wBAAwB,EACxB,yBAAyB,EAOzB,gCAAgC,EAChC,iCAAiC,EAEjC,uBAAuB,EACvB,wBAAwB,EACxB,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,YAAY,CAAC;AAiBpB,qBAAa,6BAA6B;IAI5B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAHpC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqD;IAClF,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAe;gBAEZ,OAAO,EAAE,6BAA6B;IAK7D,cAAc,IAAI,OAAO,CAAC,4BAA4B,CAAC;IA0C7D,iBAAiB,CAAC,KAAK,GAAE,gCAAqC,GAAG,iCAAiC;IAkB5F,sBAAsB,CAAC,KAAK,EAAE,+BAA+B,GAAG,OAAO,CAAC,gCAAgC,CAAC;IAyEzG,QAAQ,CAAC,KAAK,GAAE,uBAA4B,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAuEhF,QAAQ,CAAC,KAAK,EAAE,uBAAuB,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAuB3E,SAAS,CAAC,KAAK,EAAE,wBAAwB,GAAG,OAAO,CAAC,yBAAyB,CAAC;IA2S9E,MAAM,CAAC,KAAK,GAAE,qBAA0B,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAe1E,OAAO,CAAC,KAAK,GAAE,sBAA2B,GAAG,OAAO,CAAC,uBAAuB,CAAC;IA0BnF,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAC,iBAAiB;YAYX,eAAe;YAaf,oBAAoB;YAapB,wBAAwB;YAaxB,gBAAgB;YAahB,WAAW;IAOzB,OAAO,CAAC,iBAAiB;YAOX,yBAAyB;IAQvC,OAAO,CAAC,yBAAyB;YAQnB,WAAW;IAazB,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,SAAS;CAMlB"}
@@ -6,7 +6,7 @@ import { CLOUDFLARE_API_TOKEN_KEY, CLOUDFLARE_WORKER_CLIENT_TOKEN_KEY, CLOUDFLAR
6
6
  import { discoverZones, resolveZone, selectDiscoveredZone, tryDiscover, } from './discovery.js';
7
7
  import { configureDns, configureWorkerSubdomain, ensureAccess, ensureKvNamespace, ensureQueue, ensureQueueConsumer, ensureR2Bucket, ensureSecretsStore, ensureTunnel, findDurableObjectNamespace, uploadWorker, } from './resources.js';
8
8
  import { CloudflareControlPlaneError } from './types.js';
9
- import { buildTokenRequirements, buildTokenResources, clean, collectAsync, collectSingleAccount, hostnameFromUrl, requireKvNamespaceId, requireQueueId, resolveComponents, safeResponseText, selectPermissionGroups, stripTrailingSlash, } from './utils.js';
9
+ import { buildTokenRequirements, buildTokenResources, clean, collectAsync, collectSingleAccount, hostnameFromUrl, requireKvNamespaceId, requireQueueId, resolveComponents, resolvePermissionGroupIds, safeResponseText, stripTrailingSlash, } from './utils.js';
10
10
  export class CloudflareControlPlaneManager {
11
11
  options;
12
12
  createClient;
@@ -105,8 +105,7 @@ export class CloudflareControlPlaneManager {
105
105
  required: components.dns,
106
106
  });
107
107
  }
108
- const groups = await this.collectPermissionGroups(client);
109
- const permissionIds = selectPermissionGroups(requirements, groups);
108
+ const permissionIds = await this.resolvePermissionGroupIds(client, requirements);
110
109
  const resources = buildTokenResources(accountId, zone?.id, components);
111
110
  const tokenName = clean(input.tokenName) || 'GoodVibes Cloudflare Operational';
112
111
  const token = await this.requireUserTokens(client).create({
@@ -636,9 +635,9 @@ export class CloudflareControlPlaneManager {
636
635
  }
637
636
  return client.user.tokens;
638
637
  }
639
- async collectPermissionGroups(client) {
638
+ async resolvePermissionGroupIds(client, requirements) {
640
639
  const tokenApi = this.requireUserTokens(client);
641
- return await collectAsync(tokenApi.permissionGroups.list());
640
+ return await resolvePermissionGroupIds(requirements, (params) => tokenApi.permissionGroups.list(params));
642
641
  }
643
642
  createProvisioningContext() {
644
643
  return {
@@ -2,6 +2,10 @@ import type { CloudflareAccountLike, CloudflareApiClient, CloudflareComponent, C
2
2
  export declare function resolveComponents(selection: CloudflareComponentSelection | undefined): Readonly<Record<CloudflareComponent, boolean>>;
3
3
  export declare function buildTokenRequirements(components: Readonly<Record<CloudflareComponent, boolean>>, includeBootstrap: boolean): readonly CloudflareTokenPermissionRequirement[];
4
4
  export declare function selectPermissionGroups(requirements: readonly CloudflareTokenPermissionRequirement[], groups: readonly CloudflarePermissionGroupLike[]): readonly string[];
5
+ export declare function resolvePermissionGroupIds(requirements: readonly CloudflareTokenPermissionRequirement[], listPermissionGroups: (params?: {
6
+ readonly name?: string;
7
+ readonly scope?: string;
8
+ }) => AsyncIterable<CloudflarePermissionGroupLike>): Promise<readonly string[]>;
5
9
  export declare function buildTokenResources(accountId: string, zoneId: string | undefined, components: Readonly<Record<CloudflareComponent, boolean>>): Record<string, string>;
6
10
  export declare function collectSingleAccount(client: CloudflareApiClient, accountId: string, warnings: string[]): Promise<readonly CloudflareAccountLike[]>;
7
11
  export declare function collectAsync<T>(iterable: AsyncIterable<T>, limit?: number): Promise<readonly T[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/cloudflare/utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,4BAA4B,EAC5B,yBAAyB,EACzB,6BAA6B,EAC7B,mBAAmB,EACnB,oCAAoC,EACrC,MAAM,YAAY,CAAC;AAGpB,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,4BAA4B,GAAG,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,mBAAmB,EAAE,OAAO,CAAC,CAAC,CAKrI;AAED,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,mBAAmB,EAAE,OAAO,CAAC,CAAC,EAC1D,gBAAgB,EAAE,OAAO,GACxB,SAAS,oCAAoC,EAAE,CAiHjD;AAED,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,SAAS,oCAAoC,EAAE,EAC7D,MAAM,EAAE,SAAS,6BAA6B,EAAE,GAC/C,SAAS,MAAM,EAAE,CAoBnB;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,mBAAmB,EAAE,OAAO,CAAC,CAAC,GACzD,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWxB;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,mBAAmB,EAC3B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,SAAS,qBAAqB,EAAE,CAAC,CAW3C;AAED,wBAAsB,YAAY,CAAC,CAAC,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,KAAK,SAAM,GAAG,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAOpG;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAEvD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOrD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAGpF;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,yBAAyB,GAAG,MAAM,CAGjF;AAED,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAM1E"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/_internal/platform/cloudflare/utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,4BAA4B,EAC5B,yBAAyB,EACzB,6BAA6B,EAC7B,mBAAmB,EACnB,oCAAoC,EACrC,MAAM,YAAY,CAAC;AAGpB,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,4BAA4B,GAAG,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,mBAAmB,EAAE,OAAO,CAAC,CAAC,CAKrI;AAED,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,mBAAmB,EAAE,OAAO,CAAC,CAAC,EAC1D,gBAAgB,EAAE,OAAO,GACxB,SAAS,oCAAoC,EAAE,CAiHjD;AAED,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,SAAS,oCAAoC,EAAE,EAC7D,MAAM,EAAE,SAAS,6BAA6B,EAAE,GAC/C,SAAS,MAAM,EAAE,CAmBnB;AAED,wBAAsB,yBAAyB,CAC7C,YAAY,EAAE,SAAS,oCAAoC,EAAE,EAC7D,oBAAoB,EAAE,CAAC,MAAM,CAAC,EAAE;IAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,KAAK,aAAa,CAAC,6BAA6B,CAAC,GACnI,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC,CAqD5B;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,mBAAmB,EAAE,OAAO,CAAC,CAAC,GACzD,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAWxB;AAED,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,mBAAmB,EAC3B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,SAAS,qBAAqB,EAAE,CAAC,CAW3C;AAED,wBAAsB,YAAY,CAAC,CAAC,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,KAAK,SAAM,GAAG,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAOpG;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAEvD;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOrD;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAGpF;AAED,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,yBAAyB,GAAG,MAAM,CAGjF;AAED,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAM1E"}
@@ -117,8 +117,7 @@ export function selectPermissionGroups(requirements, groups) {
117
117
  const ids = [];
118
118
  const missing = [];
119
119
  for (const requirement of requirements) {
120
- const names = [requirement.permission, ...(requirement.alternatives ?? [])];
121
- const group = groups.find((entry) => entry.id && entry.name && names.some((name) => normalizePermissionName(entry.name) === normalizePermissionName(name)));
120
+ const group = findPermissionGroup(requirement, groups);
122
121
  if (group?.id) {
123
122
  ids.push(group.id);
124
123
  }
@@ -131,6 +130,54 @@ export function selectPermissionGroups(requirements, groups) {
131
130
  }
132
131
  return Array.from(new Set(ids));
133
132
  }
133
+ export async function resolvePermissionGroupIds(requirements, listPermissionGroups) {
134
+ const ids = [];
135
+ const missing = [];
136
+ let scannedGroups = null;
137
+ let lastError;
138
+ const scanAllGroups = async () => {
139
+ if (scannedGroups)
140
+ return scannedGroups;
141
+ scannedGroups = await collectAsync(listPermissionGroups(), 5_000);
142
+ return scannedGroups;
143
+ };
144
+ for (const requirement of requirements) {
145
+ const scope = cloudflareScopeForRequirement(requirement);
146
+ const names = [requirement.permission, ...(requirement.alternatives ?? [])];
147
+ let group;
148
+ for (const name of names) {
149
+ try {
150
+ const exactMatches = await collectAsync(listPermissionGroups({ name, scope }), 50);
151
+ group = findPermissionGroup(requirement, exactMatches);
152
+ if (group)
153
+ break;
154
+ }
155
+ catch (error) {
156
+ lastError = error;
157
+ break;
158
+ }
159
+ }
160
+ if (!group) {
161
+ try {
162
+ group = findPermissionGroup(requirement, await scanAllGroups());
163
+ }
164
+ catch (error) {
165
+ lastError = error;
166
+ }
167
+ }
168
+ if (group?.id) {
169
+ ids.push(group.id);
170
+ }
171
+ else {
172
+ missing.push(`${requirement.permission} (${requirement.component})`);
173
+ }
174
+ }
175
+ if (missing.length > 0) {
176
+ const suffix = lastError ? ` Last Cloudflare permission-group error: ${summarizeError(lastError)}` : '';
177
+ throw new CloudflareControlPlaneError(`Could not resolve Cloudflare permission groups for: ${missing.join(', ')}.${suffix} Use /api/cloudflare/token/requirements to show the exact required token shape and create the operational token manually if this Cloudflare account uses different permission names.`, 'CLOUDFLARE_PERMISSION_GROUPS_MISSING', 400);
178
+ }
179
+ return Array.from(new Set(ids));
180
+ }
134
181
  export function buildTokenResources(accountId, zoneId, components) {
135
182
  const resources = {
136
183
  [`com.cloudflare.api.account.${accountId}`]: '*',
@@ -211,6 +258,29 @@ function uniqueRequirements(requirements) {
211
258
  }
212
259
  return unique;
213
260
  }
261
+ function findPermissionGroup(requirement, groups) {
262
+ const names = [requirement.permission, ...(requirement.alternatives ?? [])].map(normalizePermissionName);
263
+ const scope = cloudflareScopeForRequirement(requirement);
264
+ return groups.find((entry) => entry.id &&
265
+ entry.name &&
266
+ names.includes(normalizePermissionName(entry.name)) &&
267
+ matchesPermissionScope(entry, scope));
268
+ }
269
+ function matchesPermissionScope(group, scope) {
270
+ return !group.scopes || group.scopes.length === 0 || group.scopes.includes(scope);
271
+ }
272
+ function cloudflareScopeForRequirement(requirement) {
273
+ switch (requirement.scope) {
274
+ case 'account':
275
+ return 'com.cloudflare.api.account';
276
+ case 'zone':
277
+ return 'com.cloudflare.api.account.zone';
278
+ case 'user':
279
+ return 'com.cloudflare.api.user';
280
+ case 'r2':
281
+ return 'com.cloudflare.edge.r2.bucket';
282
+ }
283
+ }
214
284
  function normalizePermissionName(value) {
215
285
  return value.toLowerCase().replace(/[^a-z0-9]+/g, '');
216
286
  }
@@ -1,6 +1,6 @@
1
1
  import { readFileSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
- let version = '0.25.14';
3
+ let version = '0.25.15';
4
4
  try {
5
5
  const pkg = JSON.parse(readFileSync(join(import.meta.dir, '..', '..', 'package.json'), 'utf-8'));
6
6
  version = pkg.version ?? version;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pellux/goodvibes-sdk",
3
- "version": "0.25.14",
3
+ "version": "0.25.15",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/mgd34msu/goodvibes-sdk.git"