@cervio/plugin-core 0.1.1 → 0.1.4

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/dist/index.cjs CHANGED
@@ -85,6 +85,68 @@ function parsePluginCervioApiRequirements(raw) {
85
85
  return out;
86
86
  }
87
87
 
88
+ // src/settings-requirements.ts
89
+ var SETTINGS_KEY_RE = /^[a-z][a-z0-9_]{0,62}$/i;
90
+ var SETTINGS_TYPES = /* @__PURE__ */ new Set(["string", "boolean", "select", "multiselect"]);
91
+ var RESERVED_SETTINGS_KEYS = /* @__PURE__ */ new Set(["debug"]);
92
+ function parseOptions(raw) {
93
+ if (!Array.isArray(raw)) return [];
94
+ const out = [];
95
+ const seen = /* @__PURE__ */ new Set();
96
+ for (const item of raw) {
97
+ if (!item || typeof item !== "object") continue;
98
+ const row = item;
99
+ const value = typeof row.value === "string" ? row.value.trim() : "";
100
+ const label = typeof row.label === "string" ? row.label.trim() : "";
101
+ if (!value || !label || seen.has(value)) continue;
102
+ seen.add(value);
103
+ out.push({ value, label });
104
+ }
105
+ return out;
106
+ }
107
+ function parseDefault(raw, type, options) {
108
+ const allowedValues = new Set(options.map((o) => o.value));
109
+ if (type === "boolean") return typeof raw === "boolean" ? raw : void 0;
110
+ if (type === "string") return typeof raw === "string" ? raw : void 0;
111
+ if (type === "select") {
112
+ return typeof raw === "string" && allowedValues.has(raw) ? raw : void 0;
113
+ }
114
+ if (type === "multiselect") {
115
+ if (!Array.isArray(raw)) return void 0;
116
+ const values = raw.filter((v) => typeof v === "string" && allowedValues.has(v));
117
+ return values.length ? values : void 0;
118
+ }
119
+ return void 0;
120
+ }
121
+ function parsePluginSettingsRequirements(raw) {
122
+ if (!Array.isArray(raw)) return [];
123
+ const out = [];
124
+ const seen = /* @__PURE__ */ new Set();
125
+ for (const item of raw) {
126
+ if (!item || typeof item !== "object") continue;
127
+ const row = item;
128
+ const key = typeof row.key === "string" ? row.key.trim() : "";
129
+ if (!key || !SETTINGS_KEY_RE.test(key) || seen.has(key) || RESERVED_SETTINGS_KEYS.has(key)) continue;
130
+ const type = typeof row.type === "string" ? row.type.trim() : null;
131
+ if (!type || !SETTINGS_TYPES.has(type)) continue;
132
+ const label = typeof row.label === "string" ? row.label.trim() : "";
133
+ if (!label) continue;
134
+ const options = parseOptions(row.options);
135
+ if ((type === "select" || type === "multiselect") && options.length === 0) continue;
136
+ const hint = typeof row.hint === "string" && row.hint.trim() ? row.hint.trim() : void 0;
137
+ const placeholder = typeof row.placeholder === "string" && row.placeholder.trim() ? row.placeholder.trim() : void 0;
138
+ const defaultValue = parseDefault(row.default, type, options);
139
+ seen.add(key);
140
+ const field = { key, type, label };
141
+ if (hint) field.hint = hint;
142
+ if (placeholder) field.placeholder = placeholder;
143
+ if (defaultValue !== void 0) field.default = defaultValue;
144
+ if (options.length) field.options = options;
145
+ out.push(field);
146
+ }
147
+ return out;
148
+ }
149
+
88
150
  // src/connections.ts
89
151
  var EXTERNAL_CONNECTION_ALLOWED_HOSTS = {
90
152
  microsoft: ["graph.microsoft.com"],
@@ -186,6 +248,7 @@ function parsePluginConnections(raw) {
186
248
  }
187
249
 
188
250
  // src/zip-safety.ts
251
+ var MAX_PLUGIN_COMPRESSION_RATIO = 100;
189
252
  function assertZipSafe(zip) {
190
253
  const names = Object.keys(zip.files);
191
254
  if (names.length > MAX_PLUGIN_ZIP_ENTRIES) {
@@ -196,11 +259,24 @@ function assertZipSafe(zip) {
196
259
  if (name.includes("..") || name.includes("\\") || name.startsWith("/")) {
197
260
  return { ok: false, error: "zip_unsafe_entry_path" };
198
261
  }
262
+ if (/\.zip$/i.test(name) && !zip.files[name]?.dir) {
263
+ return { ok: false, error: "zip_nested_archive" };
264
+ }
199
265
  const entry = zip.files[name];
200
- totalUncompressed += entry._data?.uncompressedSize ?? 0;
266
+ const uncompressed = entry._data?.uncompressedSize ?? 0;
267
+ const compressed = entry._data?.compressedSize ?? 0;
268
+ totalUncompressed += uncompressed;
201
269
  if (totalUncompressed > MAX_PLUGIN_UNCOMPRESSED_BYTES) {
202
270
  return { ok: false, error: "zip_uncompressed_too_large" };
203
271
  }
272
+ if (compressed > 0 && uncompressed > 1024 * 1024) {
273
+ const ratio = uncompressed / compressed;
274
+ if (ratio > MAX_PLUGIN_COMPRESSION_RATIO) {
275
+ return { ok: false, error: "zip_compression_ratio_too_high" };
276
+ }
277
+ } else if (compressed === 0 && uncompressed > 1024 * 1024) {
278
+ return { ok: false, error: "zip_compression_ratio_too_high" };
279
+ }
204
280
  }
205
281
  return { ok: true, value: true };
206
282
  }
@@ -241,9 +317,18 @@ var pluginManifestZodSchema = zod.z.object({
241
317
  id: zod.z.string().optional().describe("Legacy alias for plugin_key (slashes become dashes)."),
242
318
  plugin_name: zod.z.string().optional(),
243
319
  name: zod.z.string().optional().describe("Legacy alias for plugin_name."),
244
- plugin_type: zod.z.enum(["task", "form", "task_form", "route"]).optional(),
320
+ plugin_type: zod.z.enum(["task", "form", "task_form", "route", "policy", "server"]).optional().describe("Use `policy` for Policy Plugins. `server` is a legacy alias for `policy`."),
245
321
  kind: zod.z.string().optional().describe("Legacy alias for plugin_type (task_widget\u2192task, record_panel\u2192form)."),
246
- version: zod.z.string().optional().describe("Ignored by Cervio \u2014 the host assigns release versions."),
322
+ version: zod.z.string().optional().describe("Ignored by Cervio - the host assigns release versions."),
323
+ hooks: zod.z.array(
324
+ zod.z.object({
325
+ event: zod.z.enum(["before_create", "before_update"]),
326
+ entities: zod.z.array(zod.z.string()).optional(),
327
+ blocking: zod.z.boolean().optional(),
328
+ identity: zod.z.enum(["caller", "plugin_principal"]).optional(),
329
+ entry: zod.z.string().optional()
330
+ })
331
+ ).optional().describe("Policy Plugin hook declarations (plugin_type=policy; legacy server)."),
247
332
  required_connection_capabilities: zod.z.array(zod.z.string()).optional(),
248
333
  requiredConnectionCapabilities: zod.z.array(zod.z.string()).optional(),
249
334
  connections: zod.z.array(
@@ -277,8 +362,52 @@ var pluginManifestZodSchema = zod.z.object({
277
362
  pathPrefix: zod.z.string().optional()
278
363
  })
279
364
  ).optional(),
280
- cervioApis: zod.z.array(zod.z.unknown()).optional()
365
+ cervioApis: zod.z.array(zod.z.unknown()).optional(),
366
+ settings: zod.z.array(
367
+ zod.z.object({
368
+ key: zod.z.string(),
369
+ type: zod.z.enum(["string", "boolean", "select", "multiselect"]),
370
+ label: zod.z.string(),
371
+ hint: zod.z.string().optional(),
372
+ placeholder: zod.z.string().optional(),
373
+ default: zod.z.union([zod.z.string(), zod.z.boolean(), zod.z.array(zod.z.string())]).optional(),
374
+ options: zod.z.array(
375
+ zod.z.object({
376
+ value: zod.z.string(),
377
+ label: zod.z.string()
378
+ })
379
+ ).optional().describe("Required for `select` / `multiselect`.")
380
+ })
381
+ ).optional().describe("Admin-editable settings fields (drives Impostazioni dynamic form).")
281
382
  }).passthrough();
383
+
384
+ // src/policy-types.ts
385
+ function isPolicyPluginType(t) {
386
+ return t === "policy" || t === "server";
387
+ }
388
+ function normalizeToPolicyPluginType(t) {
389
+ return isPolicyPluginType(t) ? "policy" : null;
390
+ }
391
+
392
+ // src/policy-entry.ts
393
+ var BARE_IMPORT_RE = /(?:from|import)\s*\(\s*['"](?![./]|data:)([^'"]+)['"]\s*\)|(?:from|import)\s+['"](?![./]|data:)([^'"]+)['"]/g;
394
+ function findBareModuleSpecifiers(source) {
395
+ const found = /* @__PURE__ */ new Set();
396
+ for (const match of source.matchAll(BARE_IMPORT_RE)) {
397
+ const spec = (match[1] || match[2] || "").trim();
398
+ if (spec) found.add(spec);
399
+ }
400
+ return [...found];
401
+ }
402
+ function assertPolicyEntrySelfContained(source) {
403
+ const specifiers = findBareModuleSpecifiers(source);
404
+ if (specifiers.length === 0) return { ok: true };
405
+ return {
406
+ ok: false,
407
+ error: "policy_entry_not_self_contained",
408
+ specifiers
409
+ };
410
+ }
282
411
  function normalizePluginKey(raw) {
283
412
  return raw.trim().toLowerCase().replace(/[\/\s]+/g, "-").replace(/[^a-z0-9-_]/g, "-").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
284
413
  }
@@ -288,11 +417,16 @@ function resolvePluginType(raw) {
288
417
  task: "task",
289
418
  form: "form",
290
419
  task_form: "task_form",
420
+ // Legacy wire → canonical Policy Plugin type
421
+ server: "policy",
422
+ policy: "policy",
291
423
  task_widget: "task",
292
424
  record_panel: "form"
293
425
  };
294
426
  const candidate = kindMap[raw] ?? raw;
295
- return ["task", "form", "task_form", "route"].includes(candidate) ? candidate : null;
427
+ return ["task", "form", "task_form", "route", "policy", "server"].includes(
428
+ candidate
429
+ ) ? candidate : null;
296
430
  }
297
431
  function parseRequiredCapabilities(raw, allowed) {
298
432
  if (!Array.isArray(raw)) return [];
@@ -329,6 +463,7 @@ function parseManifestObject(parsed, options) {
329
463
  const cervioApis = parsePluginCervioApiRequirements(
330
464
  parsed.cervio_apis ?? parsed.cervioApis ?? []
331
465
  );
466
+ const settings = parsePluginSettingsRequirements(parsed.settings);
332
467
  return {
333
468
  ok: true,
334
469
  value: {
@@ -339,7 +474,8 @@ function parseManifestObject(parsed, options) {
339
474
  requiredConnectionCapabilities,
340
475
  connections,
341
476
  entities,
342
- cervioApis
477
+ cervioApis,
478
+ settings
343
479
  }
344
480
  };
345
481
  }
@@ -376,15 +512,37 @@ async function parseZipManifest(file, options) {
376
512
  }
377
513
  const fields = parseManifestObject(parsed, options);
378
514
  if (!fields.ok) return fields;
379
- const hasDistIndex = !!zip.file("dist/index.html");
380
- if (!hasDistIndex) return { ok: false, error: "build_index_missing" };
381
- const hasDistAssets = Object.keys(zip.files).some((name) => /^dist\/assets\/.+/.test(name));
382
- if (!hasDistAssets) return { ok: false, error: "build_assets_missing" };
515
+ const isPolicy = isPolicyPluginType(fields.value.pluginType);
516
+ if (!isPolicy) {
517
+ const hasDistIndex = !!zip.file("dist/index.html");
518
+ if (!hasDistIndex) return { ok: false, error: "build_index_missing" };
519
+ const hasDistAssets = Object.keys(zip.files).some((name) => /^dist\/assets\/.+/.test(name));
520
+ if (!hasDistAssets) return { ok: false, error: "build_assets_missing" };
521
+ }
522
+ const entryFromHooks = isPolicy && Array.isArray(parsed.hooks) ? (() => {
523
+ for (const h of parsed.hooks) {
524
+ if (typeof h?.entry === "string" && h.entry.trim()) return h.entry.trim();
525
+ }
526
+ return null;
527
+ })() : null;
528
+ const artifactEntryPath = isPolicy ? entryFromHooks || "server/index.js" : "dist/index.html";
529
+ if (isPolicy) {
530
+ const entryFile = zip.file(artifactEntryPath) || zip.file(artifactEntryPath.replace(/^\//, "")) || Object.values(zip.files).find((f) => f.name.endsWith(`/${artifactEntryPath}`));
531
+ if (!entryFile) return { ok: false, error: "manifest_not_found_in_zip" };
532
+ const entrySource = await entryFile.async("text");
533
+ const selfContained = assertPolicyEntrySelfContained(entrySource);
534
+ if (!selfContained.ok) {
535
+ return {
536
+ ok: false,
537
+ error: `${selfContained.error}:${selfContained.specifiers.join(",")}`
538
+ };
539
+ }
540
+ }
383
541
  return {
384
542
  ok: true,
385
543
  value: {
386
544
  ...fields.value,
387
- artifactEntryPath: "dist/index.html",
545
+ artifactEntryPath,
388
546
  rawManifest: parsed,
389
547
  manifestEntryName: manifestEntry.name
390
548
  }
@@ -446,11 +604,35 @@ async function packPlugin(opts) {
446
604
  }
447
605
  const fields = parseManifestObject(manifestRaw, opts.options);
448
606
  if (!fields.ok) return fields;
449
- const distIndex = path__default.default.join(root, "dist", "index.html");
450
- try {
451
- await fs.promises.access(distIndex);
452
- } catch {
453
- return { ok: false, error: "build_index_missing" };
607
+ const isPolicy = isPolicyPluginType(fields.value.pluginType);
608
+ if (!isPolicy) {
609
+ const distIndex = path__default.default.join(root, "dist", "index.html");
610
+ try {
611
+ await fs.promises.access(distIndex);
612
+ } catch {
613
+ return { ok: false, error: "build_index_missing" };
614
+ }
615
+ } else {
616
+ const entry = (Array.isArray(manifestRaw.hooks) ? manifestRaw.hooks.find((h) => h?.entry)?.entry : null) || "server/index.js";
617
+ const entryAbs = path__default.default.join(root, entry);
618
+ try {
619
+ await fs.promises.access(entryAbs);
620
+ } catch {
621
+ return { ok: false, error: "manifest_not_found_in_zip" };
622
+ }
623
+ let entrySource;
624
+ try {
625
+ entrySource = await fs.promises.readFile(entryAbs, "utf8");
626
+ } catch {
627
+ return { ok: false, error: "manifest_not_found_in_zip" };
628
+ }
629
+ const selfContained = assertPolicyEntrySelfContained(entrySource);
630
+ if (!selfContained.ok) {
631
+ return {
632
+ ok: false,
633
+ error: `${selfContained.error}:${selfContained.specifiers.join(",")}`
634
+ };
635
+ }
454
636
  }
455
637
  const zip = new JSZip__default.default();
456
638
  const files = await collectFiles(root);
@@ -465,7 +647,7 @@ async function packPlugin(opts) {
465
647
  const data = await fs.promises.readFile(file.abs);
466
648
  zip.file(file.rel, data);
467
649
  }
468
- if (!hasAssets) return { ok: false, error: "build_assets_missing" };
650
+ if (!isPolicy && !hasAssets) return { ok: false, error: "build_assets_missing" };
469
651
  const safe = assertZipSafe(zip);
470
652
  if (!safe.ok) return safe;
471
653
  const buffer = Buffer.from(await zip.generateAsync({ type: "uint8array", compression: "DEFLATE" }));
@@ -525,21 +707,26 @@ exports.OAUTH_PROVIDER_KEY_RE = OAUTH_PROVIDER_KEY_RE;
525
707
  exports.PLUGIN_ARTIFACT_BUCKET = PLUGIN_ARTIFACT_BUCKET;
526
708
  exports.PLUGIN_KEY_RE = PLUGIN_KEY_RE;
527
709
  exports.PLUGIN_VERSION_SELECT = PLUGIN_VERSION_SELECT;
710
+ exports.assertPolicyEntrySelfContained = assertPolicyEntrySelfContained;
528
711
  exports.assertZipFile = assertZipFile;
529
712
  exports.assertZipSafe = assertZipSafe;
530
713
  exports.compareSemverDesc = compareSemverDesc;
531
714
  exports.computePluginContentSha256 = computePluginContentSha256;
715
+ exports.findBareModuleSpecifiers = findBareModuleSpecifiers;
532
716
  exports.isExternalConnectionProvider = isExternalConnectionProvider;
717
+ exports.isPolicyPluginType = isPolicyPluginType;
533
718
  exports.loadZipFromBuffer = loadZipFromBuffer;
534
719
  exports.manifestJsonForContentHash = manifestJsonForContentHash;
535
720
  exports.nextPatchVersion = nextPatchVersion;
536
721
  exports.normalizeExactApiHost = normalizeExactApiHost;
537
722
  exports.normalizePluginKey = normalizePluginKey;
723
+ exports.normalizeToPolicyPluginType = normalizeToPolicyPluginType;
538
724
  exports.packPlugin = packPlugin;
539
725
  exports.parseManifestObject = parseManifestObject;
540
726
  exports.parsePluginCervioApiRequirements = parsePluginCervioApiRequirements;
541
727
  exports.parsePluginConnections = parsePluginConnections;
542
728
  exports.parsePluginEntityRequirements = parsePluginEntityRequirements;
729
+ exports.parsePluginSettingsRequirements = parsePluginSettingsRequirements;
543
730
  exports.parseZipManifest = parseZipManifest;
544
731
  exports.pluginManifestZodSchema = pluginManifestZodSchema;
545
732
  exports.sha256Hex = sha256Hex;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts","../src/entity-requirements.ts","../src/connections.ts","../src/zip-safety.ts","../src/semver.ts","../src/manifest-schema.ts","../src/manifest.ts","../src/content-hash.ts","../src/pack.ts"],"names":["path","z","JSZip","createHash","fs"],"mappings":"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","file":"index.cjs","sourcesContent":["export type PluginType = 'task' | 'form' | 'task_form' | 'route'\n\nexport type PluginActionResult<T> = { ok: true; value: T } | { ok: false; error: string }\n\nexport interface PluginVersionRow {\n id: string\n plugin_id: string\n version: string\n changelog: string | null\n artifact_path: string | null\n artifact_entry_path?: string | null\n artifact_sha256: string | null\n content_sha256?: string | null\n artifact_size_bytes: number | null\n created_at: string\n /** Soft-delete timestamp; when set the row is history-only (strikethrough in Admin). */\n deleted_at?: string | null\n deleted_by?: string | null\n}\n\nexport interface ParsedPluginManifest {\n pluginKey: string\n pluginName: string | null\n pluginType: PluginType | null\n /** Present in ZIP but ignored for assignment; Cervio owns release versions. */\n manifestVersion: string | null\n /** Catalog capability ids the plugin needs (e.g. calendar). */\n requiredConnectionCapabilities: string[]\n /** External Connections requirements (OAuth broker). */\n connections: PluginConnectionRequirement[]\n /** Declared Cervio entity deps (name-based; for Admin + future export). */\n entities: PluginEntityRequirement[]\n /** Declared Cervio API path prefixes (documentation / future allowlist). */\n cervioApis: PluginCervioApiRequirement[]\n artifactEntryPath: string\n rawManifest: Record<string, unknown>\n manifestEntryName: string\n}\n\nexport type PluginEntityAccess = 'read' | 'write'\n\nexport type PluginEntityRequirement = {\n name: string\n fields: string[]\n forms: string[]\n access: PluginEntityAccess[]\n}\n\nexport type PluginCervioApiRequirement = {\n method: string\n path_prefix: string\n}\n\nexport type ExternalConnectionHttpMethod = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE'\n\nexport type AllowedApiRule = {\n host: string\n methods: ExternalConnectionHttpMethod[]\n path_prefix: string\n}\n\nexport type PluginConnectionRequirement = {\n id: string\n provider: string\n consent: 'user'\n scopes: string[]\n allowed_apis: AllowedApiRule[]\n}\n\nexport type ParseManifestOptions = {\n /**\n * Capability ids a plugin may declare in `required_connection_capabilities`.\n * Host passes the live catalog; CLI uses {@link DEFAULT_PLUGIN_DECLARABLE_CAPABILITIES}.\n */\n allowedCapabilities?: readonly string[]\n}\n\nexport const PLUGIN_ARTIFACT_BUCKET = 'plugin-artifacts'\nexport const MAX_PLUGIN_ZIP_BYTES = 50 * 1024 * 1024\nexport const MAX_PLUGIN_ZIP_ENTRIES = 5000\nexport const MAX_PLUGIN_UNCOMPRESSED_BYTES = 250 * 1024 * 1024\nexport const PLUGIN_KEY_RE = /^[a-z0-9][a-z0-9-_]{1,62}$/\n\nexport const PLUGIN_VERSION_SELECT =\n 'id, plugin_id, version, changelog, artifact_path, artifact_entry_path, artifact_sha256, content_sha256, artifact_size_bytes, created_at, deleted_at, deleted_by'\n\n/**\n * Static default for CLI validate. Generated from host `CONNECTION_CAPABILITY_CATALOG`\n * where `pluginDeclarable === true`. Guarded by drift test against the host catalog.\n */\nexport const DEFAULT_PLUGIN_DECLARABLE_CAPABILITIES = ['calendar'] as const\n","import type {\n PluginCervioApiRequirement,\n PluginEntityAccess,\n PluginEntityRequirement,\n} from './types.js'\n\nconst ENTITY_NAME_RE = /^[a-z][a-z0-9_-]{0,62}$/i\nconst FIELD_NAME_RE = /^[a-z][a-z0-9_]{0,62}$/i\nconst HTTP_METHODS = new Set(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS', '*'])\n\nfunction asStringArray(raw: unknown, nameRe: RegExp): string[] {\n if (!Array.isArray(raw)) return []\n const out: string[] = []\n const seen = new Set<string>()\n for (const item of raw) {\n if (typeof item !== 'string') continue\n const v = item.trim()\n if (!v || !nameRe.test(v) || seen.has(v)) continue\n seen.add(v)\n out.push(v)\n }\n return out\n}\n\nfunction parseAccess(raw: unknown): PluginEntityAccess[] {\n if (!Array.isArray(raw)) return ['read']\n const out: PluginEntityAccess[] = []\n for (const item of raw) {\n if (item === 'read' || item === 'write') {\n if (!out.includes(item)) out.push(item)\n }\n }\n return out.length ? out : ['read']\n}\n\n/** Parse `entities` from manifest.json (invalid entries skipped). */\nexport function parsePluginEntityRequirements(raw: unknown): PluginEntityRequirement[] {\n if (!Array.isArray(raw)) return []\n const out: PluginEntityRequirement[] = []\n const seen = new Set<string>()\n for (const item of raw) {\n if (!item || typeof item !== 'object') continue\n const row = item as Record<string, unknown>\n const name = typeof row.name === 'string' ? row.name.trim() : ''\n if (!name || !ENTITY_NAME_RE.test(name) || seen.has(name.toLowerCase())) continue\n seen.add(name.toLowerCase())\n out.push({\n name,\n fields: asStringArray(row.fields, FIELD_NAME_RE),\n forms: asStringArray(row.forms, FIELD_NAME_RE),\n access: parseAccess(row.access),\n })\n }\n return out\n}\n\n/** Parse `cervio_apis` from manifest.json. */\nexport function parsePluginCervioApiRequirements(raw: unknown): PluginCervioApiRequirement[] {\n if (!Array.isArray(raw)) return []\n const out: PluginCervioApiRequirement[] = []\n const seen = new Set<string>()\n for (const item of raw) {\n if (!item || typeof item !== 'object') continue\n const row = item as Record<string, unknown>\n const methodRaw = typeof row.method === 'string' ? row.method.trim().toUpperCase() : 'GET'\n const method = HTTP_METHODS.has(methodRaw) ? methodRaw : 'GET'\n const path =\n typeof row.path_prefix === 'string'\n ? row.path_prefix.trim()\n : typeof row.pathPrefix === 'string'\n ? row.pathPrefix.trim()\n : ''\n if (!path || !path.startsWith('/')) continue\n const key = `${method}:${path}`\n if (seen.has(key)) continue\n seen.add(key)\n out.push({ method, path_prefix: path })\n }\n return out\n}\n","import type {\n AllowedApiRule,\n ExternalConnectionHttpMethod,\n PluginConnectionRequirement,\n} from './types.js'\n\nexport const EXTERNAL_CONNECTION_ALLOWED_HOSTS: Record<string, readonly string[]> = {\n microsoft: ['graph.microsoft.com'],\n google: ['googleapis.com', 'www.googleapis.com'],\n}\n\nexport const EXTERNAL_CONNECTION_HTTP_METHODS = [\n 'GET',\n 'POST',\n 'PATCH',\n 'PUT',\n 'DELETE',\n] as const\n\nconst CONNECTION_ID_RE = /^[a-z0-9][a-z0-9-_]{0,62}$/\nexport const OAUTH_PROVIDER_KEY_RE = /^[a-z0-9][a-z0-9_-]{0,62}$/\nconst MAX_SCOPES = 32\nconst MAX_ALLOWED_APIS = 24\nconst MAX_SCOPE_LEN = 200\n\nconst BLOCKED_HOST_SUFFIXES = ['.localhost', '.local', '.internal', '.home', '.lan']\n\n/** Lightweight host check (no DNS); mirrors host `normalizeExactApiHost` shape rules. */\nexport function normalizeExactApiHost(raw: string): string | null {\n const host = raw.trim().toLowerCase().replace(/\\.$/, '')\n if (\n !host ||\n host.length > 253 ||\n host.includes('/') ||\n host.includes(':') ||\n host.includes('*') ||\n host === 'localhost' ||\n BLOCKED_HOST_SUFFIXES.some((suffix) => host.endsWith(suffix))\n ) {\n return null\n }\n if (\n !/^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(\n host,\n )\n ) {\n return null\n }\n if (/^\\d{1,3}(\\.\\d{1,3}){3}$/.test(host)) return null\n return host\n}\n\nexport function isExternalConnectionProvider(v: string): boolean {\n return OAUTH_PROVIDER_KEY_RE.test(v)\n}\n\nfunction parseAllowedApi(raw: unknown, provider: string): AllowedApiRule | null {\n if (!raw || typeof raw !== 'object') return null\n const o = raw as Record<string, unknown>\n const host = typeof o.host === 'string' ? o.host.trim().toLowerCase() : ''\n const pathPrefix =\n typeof o.path_prefix === 'string'\n ? o.path_prefix.trim()\n : typeof o.pathPrefix === 'string'\n ? o.pathPrefix.trim()\n : ''\n const methodsRaw = o.methods\n if (!host || !pathPrefix || !normalizeExactApiHost(host)) return null\n const builtinHosts = EXTERNAL_CONNECTION_ALLOWED_HOSTS[provider]\n if (builtinHosts && !builtinHosts.includes(host)) return null\n if (!pathPrefix.startsWith('/') || pathPrefix.includes('..') || pathPrefix.includes('\\\\')) {\n return null\n }\n if (!Array.isArray(methodsRaw) || methodsRaw.length === 0) return null\n const methods: ExternalConnectionHttpMethod[] = []\n for (const m of methodsRaw) {\n if (typeof m !== 'string') return null\n const up = m.trim().toUpperCase()\n if (!(EXTERNAL_CONNECTION_HTTP_METHODS as readonly string[]).includes(up)) return null\n if (!methods.includes(up as ExternalConnectionHttpMethod)) {\n methods.push(up as ExternalConnectionHttpMethod)\n }\n }\n if (!methods.length) return null\n return { host, methods, path_prefix: pathPrefix }\n}\n\n/** Parse manifest `connections` array; drops invalid entries. */\nexport function parsePluginConnections(raw: unknown): PluginConnectionRequirement[] {\n if (!Array.isArray(raw)) return []\n const out: PluginConnectionRequirement[] = []\n const seen = new Set<string>()\n for (const item of raw) {\n if (!item || typeof item !== 'object') continue\n const o = item as Record<string, unknown>\n const id = typeof o.id === 'string' ? o.id.trim().toLowerCase() : ''\n if (!id || !CONNECTION_ID_RE.test(id) || seen.has(id)) continue\n const providerRaw = typeof o.provider === 'string' ? o.provider.trim().toLowerCase() : ''\n if (!isExternalConnectionProvider(providerRaw)) continue\n const scopesRaw = o.scopes\n if (!Array.isArray(scopesRaw) || scopesRaw.length === 0 || scopesRaw.length > MAX_SCOPES) continue\n const scopes: string[] = []\n for (const s of scopesRaw) {\n if (typeof s !== 'string') continue\n const t = s.trim()\n if (!t || t.length > MAX_SCOPE_LEN) continue\n if (!scopes.includes(t)) scopes.push(t)\n }\n if (!scopes.length) continue\n const apisRaw = o.allowed_apis ?? o.allowedApis\n if (!Array.isArray(apisRaw) || apisRaw.length === 0 || apisRaw.length > MAX_ALLOWED_APIS) continue\n const allowed_apis: AllowedApiRule[] = []\n for (const a of apisRaw) {\n const rule = parseAllowedApi(a, providerRaw)\n if (rule) allowed_apis.push(rule)\n }\n if (!allowed_apis.length) continue\n seen.add(id)\n out.push({\n id,\n provider: providerRaw,\n consent: 'user',\n scopes,\n allowed_apis,\n })\n }\n return out\n}\n","import type JSZip from 'jszip'\nimport {\n MAX_PLUGIN_UNCOMPRESSED_BYTES,\n MAX_PLUGIN_ZIP_BYTES,\n MAX_PLUGIN_ZIP_ENTRIES,\n type PluginActionResult,\n} from './types.js'\n\n/**\n * Validates a loaded plugin ZIP before any entry is inflated (CERVIO-SEC-014):\n * caps the entry count and total declared uncompressed size to stop zip bombs,\n * and rejects path-traversal / absolute entry names as defense-in-depth.\n */\nexport function assertZipSafe(zip: JSZip): PluginActionResult<true> {\n const names = Object.keys(zip.files)\n if (names.length > MAX_PLUGIN_ZIP_ENTRIES) {\n return { ok: false, error: 'zip_too_many_entries' }\n }\n let totalUncompressed = 0\n for (const name of names) {\n if (name.includes('..') || name.includes('\\\\') || name.startsWith('/')) {\n return { ok: false, error: 'zip_unsafe_entry_path' }\n }\n const entry = zip.files[name] as JSZip.JSZipObject & {\n _data?: { uncompressedSize?: number }\n }\n totalUncompressed += entry._data?.uncompressedSize ?? 0\n if (totalUncompressed > MAX_PLUGIN_UNCOMPRESSED_BYTES) {\n return { ok: false, error: 'zip_uncompressed_too_large' }\n }\n }\n return { ok: true, value: true }\n}\n\nexport function assertZipFile(file: { name?: string; size: number }): PluginActionResult<true> {\n const name = (file.name ?? 'upload.zip').toLowerCase()\n if (!name.endsWith('.zip')) return { ok: false, error: 'invalid_file_extension' }\n if (file.size <= 0) return { ok: false, error: 'empty_file' }\n if (file.size > MAX_PLUGIN_ZIP_BYTES) return { ok: false, error: 'file_too_large' }\n return { ok: true, value: true }\n}\n","const CORE_SEMVER_RE = /^(\\d+)\\.(\\d+)\\.(\\d+)/\n\n/**\n * Next patch version assigned by Cervio. Ignores pre-release/build metadata on\n * the previous label and bumps the patch component only.\n */\nexport function nextPatchVersion(latest: string | null | undefined): string {\n if (!latest || typeof latest !== 'string') return '0.1.0'\n const m = latest.trim().match(CORE_SEMVER_RE)\n if (!m) return '0.1.0'\n const major = Number(m[1])\n const minor = Number(m[2])\n const patch = Number(m[3])\n if (![major, minor, patch].every((n) => Number.isFinite(n) && n >= 0)) return '0.1.0'\n return `${major}.${minor}.${patch + 1}`\n}\n\n/** Compare core x.y.z numerically (descending sort helper). */\nexport function compareSemverDesc(a: string, b: string): number {\n const pa = a.match(CORE_SEMVER_RE)\n const pb = b.match(CORE_SEMVER_RE)\n if (!pa && !pb) return 0\n if (!pa) return 1\n if (!pb) return -1\n for (let i = 1; i <= 3; i++) {\n const da = Number(pa[i]) - Number(pb[i])\n if (da !== 0) return da > 0 ? -1 : 1\n }\n return 0\n}\n","import { z } from 'zod'\n\n/** Zod schema documenting the author-facing manifest shape (source of truth for JSON Schema). */\nexport const pluginManifestZodSchema = z\n .object({\n plugin_key: z\n .string()\n .regex(/^[a-z0-9][a-z0-9-_]{1,62}$/)\n .optional()\n .describe('Stable plugin id. Prefer this over legacy `id`.'),\n id: z.string().optional().describe('Legacy alias for plugin_key (slashes become dashes).'),\n plugin_name: z.string().optional(),\n name: z.string().optional().describe('Legacy alias for plugin_name.'),\n plugin_type: z.enum(['task', 'form', 'task_form', 'route']).optional(),\n kind: z\n .string()\n .optional()\n .describe('Legacy alias for plugin_type (task_widget→task, record_panel→form).'),\n version: z\n .string()\n .optional()\n .describe('Ignored by Cervio — the host assigns release versions.'),\n required_connection_capabilities: z.array(z.string()).optional(),\n requiredConnectionCapabilities: z.array(z.string()).optional(),\n connections: z\n .array(\n z.object({\n id: z.string(),\n provider: z.string(),\n scopes: z.array(z.string()),\n allowed_apis: z\n .array(\n z.object({\n host: z.string(),\n methods: z.array(z.string()),\n path_prefix: z.string().optional(),\n pathPrefix: z.string().optional(),\n }),\n )\n .optional(),\n allowedApis: z.array(z.unknown()).optional(),\n }),\n )\n .optional(),\n entities: z\n .array(\n z.object({\n name: z.string(),\n fields: z.array(z.string()).optional(),\n forms: z.array(z.string()).optional(),\n access: z.array(z.enum(['read', 'write'])).optional(),\n }),\n )\n .optional(),\n cervio_apis: z\n .array(\n z.object({\n method: z.string().optional(),\n path_prefix: z.string().optional(),\n pathPrefix: z.string().optional(),\n }),\n )\n .optional(),\n cervioApis: z.array(z.unknown()).optional(),\n })\n .passthrough()\n\nexport type PluginManifestZod = z.infer<typeof pluginManifestZodSchema>\n","import JSZip from 'jszip'\nimport { parsePluginConnections } from './connections.js'\nimport {\n parsePluginCervioApiRequirements,\n parsePluginEntityRequirements,\n} from './entity-requirements.js'\nimport {\n DEFAULT_PLUGIN_DECLARABLE_CAPABILITIES,\n PLUGIN_KEY_RE,\n type ParseManifestOptions,\n type ParsedPluginManifest,\n type PluginActionResult,\n type PluginCervioApiRequirement,\n type PluginConnectionRequirement,\n type PluginEntityRequirement,\n type PluginType,\n} from './types.js'\nimport { assertZipSafe } from './zip-safety.js'\n\nexport function normalizePluginKey(raw: string): string {\n return raw\n .trim()\n .toLowerCase()\n .replace(/[\\/\\s]+/g, '-')\n .replace(/[^a-z0-9-_]/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-+|-+$/g, '')\n}\n\nfunction resolvePluginType(raw: string): PluginType | null {\n const kindMap: Record<string, PluginType> = {\n route: 'route',\n task: 'task',\n form: 'form',\n task_form: 'task_form',\n task_widget: 'task',\n record_panel: 'form',\n }\n const candidate = kindMap[raw] ?? raw\n return (['task', 'form', 'task_form', 'route'] as const).includes(candidate as PluginType)\n ? (candidate as PluginType)\n : null\n}\n\nfunction parseRequiredCapabilities(\n raw: unknown,\n allowed: readonly string[],\n): string[] {\n if (!Array.isArray(raw)) return []\n const allowedSet = new Set(allowed)\n const out: string[] = []\n const seen = new Set<string>()\n for (const item of raw) {\n if (typeof item !== 'string') continue\n const id = item.trim().toLowerCase()\n if (!id || !allowedSet.has(id) || seen.has(id)) continue\n seen.add(id)\n out.push(id)\n }\n return out\n}\n\nexport function parseManifestObject(\n parsed: Record<string, unknown>,\n options?: ParseManifestOptions,\n): PluginActionResult<{\n pluginKey: string\n pluginName: string | null\n pluginType: PluginType | null\n manifestVersion: string | null\n requiredConnectionCapabilities: string[]\n connections: PluginConnectionRequirement[]\n entities: PluginEntityRequirement[]\n cervioApis: PluginCervioApiRequirement[]\n}> {\n const allowedCapabilities =\n options?.allowedCapabilities ?? DEFAULT_PLUGIN_DECLARABLE_CAPABILITIES\n\n const pluginKeyRaw =\n typeof parsed.plugin_key === 'string'\n ? parsed.plugin_key\n : typeof parsed.id === 'string'\n ? parsed.id.split('/').filter(Boolean).join('-')\n : ''\n const pluginKey = normalizePluginKey(pluginKeyRaw)\n if (!pluginKey || !PLUGIN_KEY_RE.test(pluginKey)) {\n return { ok: false, error: 'manifest_plugin_key_invalid' }\n }\n const pluginName =\n typeof parsed.plugin_name === 'string' && parsed.plugin_name.trim()\n ? parsed.plugin_name.trim()\n : typeof parsed.name === 'string' && parsed.name.trim()\n ? parsed.name.trim()\n : null\n\n const pluginTypeRaw =\n typeof parsed.plugin_type === 'string'\n ? parsed.plugin_type.trim()\n : typeof parsed.kind === 'string'\n ? parsed.kind.trim()\n : ''\n const pluginType = resolvePluginType(pluginTypeRaw)\n\n const manifestVersion =\n typeof parsed.version === 'string' && parsed.version.trim() ? parsed.version.trim() : null\n\n const requiredRaw =\n parsed.required_connection_capabilities ?? parsed.requiredConnectionCapabilities ?? []\n const requiredConnectionCapabilities = parseRequiredCapabilities(\n requiredRaw,\n allowedCapabilities,\n )\n\n const connections = parsePluginConnections(parsed.connections)\n const entities = parsePluginEntityRequirements(parsed.entities)\n const cervioApis = parsePluginCervioApiRequirements(\n parsed.cervio_apis ?? parsed.cervioApis ?? [],\n )\n\n return {\n ok: true,\n value: {\n pluginKey,\n pluginName,\n pluginType,\n manifestVersion,\n requiredConnectionCapabilities,\n connections,\n entities,\n cervioApis,\n },\n }\n}\n\n/** Manifest JSON for hashing: drop author `version` so Cervio-owned labels do not affect dedup. */\nexport function manifestJsonForContentHash(raw: Record<string, unknown>): string {\n const clone: Record<string, unknown> = { ...raw }\n delete clone.version\n return JSON.stringify(clone)\n}\n\nexport async function loadZipFromBuffer(\n buffer: ArrayBuffer | Buffer,\n): Promise<PluginActionResult<JSZip>> {\n try {\n const zip = await JSZip.loadAsync(buffer)\n const safe = assertZipSafe(zip)\n if (!safe.ok) return safe\n return { ok: true, value: zip }\n } catch {\n return { ok: false, error: 'zip_invalid' }\n }\n}\n\nexport async function parseZipManifest(\n file: File | Blob,\n options?: ParseManifestOptions,\n): Promise<PluginActionResult<ParsedPluginManifest>> {\n const buffer = await file.arrayBuffer()\n const zipRes = await loadZipFromBuffer(buffer)\n if (!zipRes.ok) return zipRes\n const zip = zipRes.value\n\n const manifestEntry =\n zip.file('manifest.json') ??\n zip.file('manifest.example.json') ??\n Object.values(zip.files).find(\n (f) => f.name.endsWith('/manifest.json') || f.name.endsWith('/manifest.example.json'),\n )\n if (!manifestEntry) return { ok: false, error: 'manifest_not_found_in_zip' }\n\n const jsonText = await manifestEntry.async('text')\n let parsed: Record<string, unknown>\n try {\n parsed = JSON.parse(jsonText) as Record<string, unknown>\n } catch {\n return { ok: false, error: 'manifest_invalid_json' }\n }\n\n const fields = parseManifestObject(parsed, options)\n if (!fields.ok) return fields\n\n const hasDistIndex = !!zip.file('dist/index.html')\n if (!hasDistIndex) return { ok: false, error: 'build_index_missing' }\n const hasDistAssets = Object.keys(zip.files).some((name) => /^dist\\/assets\\/.+/.test(name))\n if (!hasDistAssets) return { ok: false, error: 'build_assets_missing' }\n\n return {\n ok: true,\n value: {\n ...fields.value,\n artifactEntryPath: 'dist/index.html',\n rawManifest: parsed,\n manifestEntryName: manifestEntry.name,\n },\n }\n}\n","import { createHash } from 'node:crypto'\nimport type JSZip from 'jszip'\nimport { manifestJsonForContentHash } from './manifest.js'\nimport type { PluginActionResult } from './types.js'\n\n/**\n * Deterministic SHA-256 over:\n * - manifest.json (JSON without `version` field)\n * - every non-directory entry under dist/** (paths sorted)\n *\n * README / other root files and ZIP compression metadata do not affect the hash.\n */\nexport async function computePluginContentSha256(\n zip: JSZip,\n rawManifest: Record<string, unknown>,\n): Promise<PluginActionResult<string>> {\n try {\n const hash = createHash('sha256')\n hash.update('manifest\\0')\n hash.update(manifestJsonForContentHash(rawManifest))\n hash.update('\\0')\n\n const distPaths = Object.keys(zip.files)\n .filter((name) => {\n const entry = zip.files[name]\n if (!entry || entry.dir) return false\n const normalized = name.replace(/^\\.\\//, '')\n return normalized === 'dist' || normalized.startsWith('dist/')\n })\n .map((name) => name.replace(/^\\.\\//, ''))\n .sort((a, b) => a.localeCompare(b))\n\n for (const path of distPaths) {\n const entry = zip.file(path)\n if (!entry || entry.dir) continue\n const bytes = await entry.async('uint8array')\n hash.update('file\\0')\n hash.update(path)\n hash.update('\\0')\n hash.update(bytes)\n hash.update('\\0')\n }\n\n return { ok: true, value: hash.digest('hex') }\n } catch {\n return { ok: false, error: 'content_hash_failed' }\n }\n}\n\nexport function sha256Hex(buffer: Buffer | Uint8Array): string {\n return createHash('sha256').update(buffer).digest('hex')\n}\n","import { promises as fs } from 'node:fs'\nimport path from 'node:path'\nimport JSZip from 'jszip'\nimport { computePluginContentSha256 } from './content-hash.js'\nimport { loadZipFromBuffer, parseManifestObject, parseZipManifest } from './manifest.js'\nimport type { ParseManifestOptions, PluginActionResult } from './types.js'\nimport { assertZipFile, assertZipSafe } from './zip-safety.js'\n\nexport type PackPluginResult = {\n buffer: Buffer\n pluginKey: string\n contentSha256: string\n sizeBytes: number\n}\n\nasync function collectFiles(dir: string, base = ''): Promise<Array<{ rel: string; abs: string }>> {\n const entries = await fs.readdir(dir, { withFileTypes: true })\n const out: Array<{ rel: string; abs: string }> = []\n for (const entry of entries) {\n const abs = path.join(dir, entry.name)\n const rel = base ? `${base}/${entry.name}` : entry.name\n if (entry.isDirectory()) {\n out.push(...(await collectFiles(abs, rel)))\n } else if (entry.isFile()) {\n out.push({ rel: rel.replace(/\\\\/g, '/'), abs })\n }\n }\n return out\n}\n\n/**\n * Pack a built plugin directory into a ZIP buffer.\n * Expects `manifest.json` at root and `dist/index.html` + `dist/assets/*`.\n */\nexport async function packPlugin(opts: {\n dir: string\n options?: ParseManifestOptions\n}): Promise<PluginActionResult<PackPluginResult>> {\n const root = path.resolve(opts.dir)\n const manifestPath = path.join(root, 'manifest.json')\n let manifestRaw: Record<string, unknown>\n try {\n const text = await fs.readFile(manifestPath, 'utf8')\n manifestRaw = JSON.parse(text) as Record<string, unknown>\n } catch {\n return { ok: false, error: 'manifest_not_found_in_zip' }\n }\n\n const fields = parseManifestObject(manifestRaw, opts.options)\n if (!fields.ok) return fields\n\n const distIndex = path.join(root, 'dist', 'index.html')\n try {\n await fs.access(distIndex)\n } catch {\n return { ok: false, error: 'build_index_missing' }\n }\n\n const zip = new JSZip()\n const files = await collectFiles(root)\n let hasAssets = false\n for (const file of files) {\n if (file.rel.startsWith('.cervio/') || file.rel === 'node_modules' || file.rel.startsWith('node_modules/')) {\n continue\n }\n if (file.rel.startsWith('dist/assets/') && file.rel !== 'dist/assets/') {\n hasAssets = true\n }\n const data = await fs.readFile(file.abs)\n zip.file(file.rel, data)\n }\n if (!hasAssets) return { ok: false, error: 'build_assets_missing' }\n\n const safe = assertZipSafe(zip)\n if (!safe.ok) return safe\n\n const buffer = Buffer.from(await zip.generateAsync({ type: 'uint8array', compression: 'DEFLATE' }))\n const fileCheck = assertZipFile({ name: `${fields.value.pluginKey}.zip`, size: buffer.length })\n if (!fileCheck.ok) return fileCheck\n\n const loaded = await loadZipFromBuffer(buffer)\n if (!loaded.ok) return loaded\n const hash = await computePluginContentSha256(loaded.value, manifestRaw)\n if (!hash.ok) return hash\n\n return {\n ok: true,\n value: {\n buffer,\n pluginKey: fields.value.pluginKey,\n contentSha256: hash.value,\n sizeBytes: buffer.length,\n },\n }\n}\n\n/** Validate an on-disk plugin directory (or an existing ZIP) without uploading. */\nexport async function validatePluginDir(\n dir: string,\n options?: ParseManifestOptions,\n): Promise<PluginActionResult<{ pluginKey: string; contentSha256: string }>> {\n const packed = await packPlugin({ dir, options })\n if (!packed.ok) return packed\n const blob = new Blob([packed.value.buffer], { type: 'application/zip' })\n const parsed = await parseZipManifest(blob, options)\n if (!parsed.ok) return parsed\n return {\n ok: true,\n value: {\n pluginKey: packed.value.pluginKey,\n contentSha256: packed.value.contentSha256,\n },\n }\n}\n\nexport async function validatePluginZipBuffer(\n buffer: Buffer,\n options?: ParseManifestOptions,\n): Promise<PluginActionResult<{ pluginKey: string; contentSha256: string }>> {\n const fileCheck = assertZipFile({ name: 'plugin.zip', size: buffer.length })\n if (!fileCheck.ok) return fileCheck\n const blob = new Blob([buffer], { type: 'application/zip' })\n const parsed = await parseZipManifest(blob, options)\n if (!parsed.ok) return parsed\n const zipRes = await loadZipFromBuffer(buffer)\n if (!zipRes.ok) return zipRes\n const hash = await computePluginContentSha256(zipRes.value, parsed.value.rawManifest)\n if (!hash.ok) return hash\n return {\n ok: true,\n value: { pluginKey: parsed.value.pluginKey, contentSha256: hash.value },\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/types.ts","../src/entity-requirements.ts","../src/settings-requirements.ts","../src/connections.ts","../src/zip-safety.ts","../src/semver.ts","../src/manifest-schema.ts","../src/policy-types.ts","../src/policy-entry.ts","../src/manifest.ts","../src/content-hash.ts","../src/pack.ts"],"names":["path","z","JSZip","createHash","fs"],"mappings":"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","file":"index.cjs","sourcesContent":["/** Canonical Policy Plugin type is `policy`; `server` is a silent legacy alias. */\nexport type PluginType = 'task' | 'form' | 'task_form' | 'route' | 'policy' | 'server'\n\nexport type PluginActionResult<T> = { ok: true; value: T } | { ok: false; error: string }\n\nexport interface PluginVersionRow {\n id: string\n plugin_id: string\n version: string\n changelog: string | null\n artifact_path: string | null\n artifact_entry_path?: string | null\n artifact_sha256: string | null\n content_sha256?: string | null\n artifact_size_bytes: number | null\n created_at: string\n /** Soft-delete timestamp; when set the row is history-only (strikethrough in Admin). */\n deleted_at?: string | null\n deleted_by?: string | null\n}\n\nexport interface ParsedPluginManifest {\n pluginKey: string\n pluginName: string | null\n pluginType: PluginType | null\n /** Present in ZIP but ignored for assignment; Cervio owns release versions. */\n manifestVersion: string | null\n /** Catalog capability ids the plugin needs (e.g. calendar). */\n requiredConnectionCapabilities: string[]\n /** External Connections requirements (OAuth broker). */\n connections: PluginConnectionRequirement[]\n /** Declared Cervio entity deps (name-based; for Admin + future export). */\n entities: PluginEntityRequirement[]\n /** Declared Cervio API path prefixes (documentation / future allowlist). */\n cervioApis: PluginCervioApiRequirement[]\n /** Declared Admin-editable settings fields (drives Impostazioni dynamic form). */\n settings: PluginSettingsFieldRequirement[]\n artifactEntryPath: string\n rawManifest: Record<string, unknown>\n manifestEntryName: string\n}\n\nexport type PluginEntityAccess = 'read' | 'write'\n\nexport type PluginEntityRequirement = {\n name: string\n fields: string[]\n forms: string[]\n access: PluginEntityAccess[]\n}\n\nexport type PluginCervioApiRequirement = {\n method: string\n path_prefix: string\n}\n\nexport type PluginSettingsFieldType = 'string' | 'boolean' | 'select' | 'multiselect'\n\nexport type PluginSettingsFieldOption = {\n value: string\n label: string\n}\n\nexport type PluginSettingsFieldRequirement = {\n key: string\n type: PluginSettingsFieldType\n label: string\n hint?: string\n placeholder?: string\n default?: string | boolean | string[]\n /** Required for `select` / `multiselect`. */\n options?: PluginSettingsFieldOption[]\n}\n\nexport type ExternalConnectionHttpMethod = 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE'\n\nexport type AllowedApiRule = {\n host: string\n methods: ExternalConnectionHttpMethod[]\n path_prefix: string\n}\n\nexport type PluginConnectionRequirement = {\n id: string\n provider: string\n consent: 'user'\n scopes: string[]\n allowed_apis: AllowedApiRule[]\n}\n\nexport type ParseManifestOptions = {\n /**\n * Capability ids a plugin may declare in `required_connection_capabilities`.\n * Host passes the live catalog; CLI uses {@link DEFAULT_PLUGIN_DECLARABLE_CAPABILITIES}.\n */\n allowedCapabilities?: readonly string[]\n}\n\nexport const PLUGIN_ARTIFACT_BUCKET = 'plugin-artifacts'\nexport const MAX_PLUGIN_ZIP_BYTES = 50 * 1024 * 1024\nexport const MAX_PLUGIN_ZIP_ENTRIES = 5000\nexport const MAX_PLUGIN_UNCOMPRESSED_BYTES = 250 * 1024 * 1024\nexport const PLUGIN_KEY_RE = /^[a-z0-9][a-z0-9-_]{1,62}$/\n\nexport const PLUGIN_VERSION_SELECT =\n 'id, plugin_id, version, changelog, artifact_path, artifact_entry_path, artifact_sha256, content_sha256, artifact_size_bytes, created_at, deleted_at, deleted_by'\n\n/**\n * Static default for CLI validate. Generated from host `CONNECTION_CAPABILITY_CATALOG`\n * where `pluginDeclarable === true`. Guarded by drift test against the host catalog.\n */\nexport const DEFAULT_PLUGIN_DECLARABLE_CAPABILITIES = ['calendar'] as const\n","import type {\n PluginCervioApiRequirement,\n PluginEntityAccess,\n PluginEntityRequirement,\n} from './types.js'\n\nconst ENTITY_NAME_RE = /^[a-z][a-z0-9_-]{0,62}$/i\nconst FIELD_NAME_RE = /^[a-z][a-z0-9_]{0,62}$/i\nconst HTTP_METHODS = new Set(['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS', '*'])\n\nfunction asStringArray(raw: unknown, nameRe: RegExp): string[] {\n if (!Array.isArray(raw)) return []\n const out: string[] = []\n const seen = new Set<string>()\n for (const item of raw) {\n if (typeof item !== 'string') continue\n const v = item.trim()\n if (!v || !nameRe.test(v) || seen.has(v)) continue\n seen.add(v)\n out.push(v)\n }\n return out\n}\n\nfunction parseAccess(raw: unknown): PluginEntityAccess[] {\n if (!Array.isArray(raw)) return ['read']\n const out: PluginEntityAccess[] = []\n for (const item of raw) {\n if (item === 'read' || item === 'write') {\n if (!out.includes(item)) out.push(item)\n }\n }\n return out.length ? out : ['read']\n}\n\n/** Parse `entities` from manifest.json (invalid entries skipped). */\nexport function parsePluginEntityRequirements(raw: unknown): PluginEntityRequirement[] {\n if (!Array.isArray(raw)) return []\n const out: PluginEntityRequirement[] = []\n const seen = new Set<string>()\n for (const item of raw) {\n if (!item || typeof item !== 'object') continue\n const row = item as Record<string, unknown>\n const name = typeof row.name === 'string' ? row.name.trim() : ''\n if (!name || !ENTITY_NAME_RE.test(name) || seen.has(name.toLowerCase())) continue\n seen.add(name.toLowerCase())\n out.push({\n name,\n fields: asStringArray(row.fields, FIELD_NAME_RE),\n forms: asStringArray(row.forms, FIELD_NAME_RE),\n access: parseAccess(row.access),\n })\n }\n return out\n}\n\n/** Parse `cervio_apis` from manifest.json. */\nexport function parsePluginCervioApiRequirements(raw: unknown): PluginCervioApiRequirement[] {\n if (!Array.isArray(raw)) return []\n const out: PluginCervioApiRequirement[] = []\n const seen = new Set<string>()\n for (const item of raw) {\n if (!item || typeof item !== 'object') continue\n const row = item as Record<string, unknown>\n const methodRaw = typeof row.method === 'string' ? row.method.trim().toUpperCase() : 'GET'\n const method = HTTP_METHODS.has(methodRaw) ? methodRaw : 'GET'\n const path =\n typeof row.path_prefix === 'string'\n ? row.path_prefix.trim()\n : typeof row.pathPrefix === 'string'\n ? row.pathPrefix.trim()\n : ''\n if (!path || !path.startsWith('/')) continue\n const key = `${method}:${path}`\n if (seen.has(key)) continue\n seen.add(key)\n out.push({ method, path_prefix: path })\n }\n return out\n}\n","import type {\n PluginSettingsFieldOption,\n PluginSettingsFieldRequirement,\n PluginSettingsFieldType,\n} from './types.js'\n\nconst SETTINGS_KEY_RE = /^[a-z][a-z0-9_]{0,62}$/i\nconst SETTINGS_TYPES = new Set<PluginSettingsFieldType>(['string', 'boolean', 'select', 'multiselect'])\n\n/** Keys the host reserves for itself (e.g. `debug` is the host-level runtime toggle). */\nconst RESERVED_SETTINGS_KEYS = new Set(['debug'])\n\nfunction parseOptions(raw: unknown): PluginSettingsFieldOption[] {\n if (!Array.isArray(raw)) return []\n const out: PluginSettingsFieldOption[] = []\n const seen = new Set<string>()\n for (const item of raw) {\n if (!item || typeof item !== 'object') continue\n const row = item as Record<string, unknown>\n const value = typeof row.value === 'string' ? row.value.trim() : ''\n const label = typeof row.label === 'string' ? row.label.trim() : ''\n if (!value || !label || seen.has(value)) continue\n seen.add(value)\n out.push({ value, label })\n }\n return out\n}\n\nfunction parseDefault(\n raw: unknown,\n type: PluginSettingsFieldType,\n options: PluginSettingsFieldOption[],\n): string | boolean | string[] | undefined {\n const allowedValues = new Set(options.map((o) => o.value))\n if (type === 'boolean') return typeof raw === 'boolean' ? raw : undefined\n if (type === 'string') return typeof raw === 'string' ? raw : undefined\n if (type === 'select') {\n return typeof raw === 'string' && allowedValues.has(raw) ? raw : undefined\n }\n if (type === 'multiselect') {\n if (!Array.isArray(raw)) return undefined\n const values = raw.filter((v): v is string => typeof v === 'string' && allowedValues.has(v))\n return values.length ? values : undefined\n }\n return undefined\n}\n\n/** Parse `settings` from manifest.json (invalid entries skipped). */\nexport function parsePluginSettingsRequirements(raw: unknown): PluginSettingsFieldRequirement[] {\n if (!Array.isArray(raw)) return []\n const out: PluginSettingsFieldRequirement[] = []\n const seen = new Set<string>()\n for (const item of raw) {\n if (!item || typeof item !== 'object') continue\n const row = item as Record<string, unknown>\n\n const key = typeof row.key === 'string' ? row.key.trim() : ''\n if (!key || !SETTINGS_KEY_RE.test(key) || seen.has(key) || RESERVED_SETTINGS_KEYS.has(key)) continue\n\n const type = typeof row.type === 'string' ? (row.type.trim() as PluginSettingsFieldType) : null\n if (!type || !SETTINGS_TYPES.has(type)) continue\n\n const label = typeof row.label === 'string' ? row.label.trim() : ''\n if (!label) continue\n\n const options = parseOptions(row.options)\n if ((type === 'select' || type === 'multiselect') && options.length === 0) continue\n\n const hint = typeof row.hint === 'string' && row.hint.trim() ? row.hint.trim() : undefined\n const placeholder =\n typeof row.placeholder === 'string' && row.placeholder.trim() ? row.placeholder.trim() : undefined\n const defaultValue = parseDefault(row.default, type, options)\n\n seen.add(key)\n const field: PluginSettingsFieldRequirement = { key, type, label }\n if (hint) field.hint = hint\n if (placeholder) field.placeholder = placeholder\n if (defaultValue !== undefined) field.default = defaultValue\n if (options.length) field.options = options\n out.push(field)\n }\n return out\n}\n","import type {\n AllowedApiRule,\n ExternalConnectionHttpMethod,\n PluginConnectionRequirement,\n} from './types.js'\n\nexport const EXTERNAL_CONNECTION_ALLOWED_HOSTS: Record<string, readonly string[]> = {\n microsoft: ['graph.microsoft.com'],\n google: ['googleapis.com', 'www.googleapis.com'],\n}\n\nexport const EXTERNAL_CONNECTION_HTTP_METHODS = [\n 'GET',\n 'POST',\n 'PATCH',\n 'PUT',\n 'DELETE',\n] as const\n\nconst CONNECTION_ID_RE = /^[a-z0-9][a-z0-9-_]{0,62}$/\nexport const OAUTH_PROVIDER_KEY_RE = /^[a-z0-9][a-z0-9_-]{0,62}$/\nconst MAX_SCOPES = 32\nconst MAX_ALLOWED_APIS = 24\nconst MAX_SCOPE_LEN = 200\n\nconst BLOCKED_HOST_SUFFIXES = ['.localhost', '.local', '.internal', '.home', '.lan']\n\n/** Lightweight host check (no DNS); mirrors host `normalizeExactApiHost` shape rules. */\nexport function normalizeExactApiHost(raw: string): string | null {\n const host = raw.trim().toLowerCase().replace(/\\.$/, '')\n if (\n !host ||\n host.length > 253 ||\n host.includes('/') ||\n host.includes(':') ||\n host.includes('*') ||\n host === 'localhost' ||\n BLOCKED_HOST_SUFFIXES.some((suffix) => host.endsWith(suffix))\n ) {\n return null\n }\n if (\n !/^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(\n host,\n )\n ) {\n return null\n }\n if (/^\\d{1,3}(\\.\\d{1,3}){3}$/.test(host)) return null\n return host\n}\n\nexport function isExternalConnectionProvider(v: string): boolean {\n return OAUTH_PROVIDER_KEY_RE.test(v)\n}\n\nfunction parseAllowedApi(raw: unknown, provider: string): AllowedApiRule | null {\n if (!raw || typeof raw !== 'object') return null\n const o = raw as Record<string, unknown>\n const host = typeof o.host === 'string' ? o.host.trim().toLowerCase() : ''\n const pathPrefix =\n typeof o.path_prefix === 'string'\n ? o.path_prefix.trim()\n : typeof o.pathPrefix === 'string'\n ? o.pathPrefix.trim()\n : ''\n const methodsRaw = o.methods\n if (!host || !pathPrefix || !normalizeExactApiHost(host)) return null\n const builtinHosts = EXTERNAL_CONNECTION_ALLOWED_HOSTS[provider]\n if (builtinHosts && !builtinHosts.includes(host)) return null\n if (!pathPrefix.startsWith('/') || pathPrefix.includes('..') || pathPrefix.includes('\\\\')) {\n return null\n }\n if (!Array.isArray(methodsRaw) || methodsRaw.length === 0) return null\n const methods: ExternalConnectionHttpMethod[] = []\n for (const m of methodsRaw) {\n if (typeof m !== 'string') return null\n const up = m.trim().toUpperCase()\n if (!(EXTERNAL_CONNECTION_HTTP_METHODS as readonly string[]).includes(up)) return null\n if (!methods.includes(up as ExternalConnectionHttpMethod)) {\n methods.push(up as ExternalConnectionHttpMethod)\n }\n }\n if (!methods.length) return null\n return { host, methods, path_prefix: pathPrefix }\n}\n\n/** Parse manifest `connections` array; drops invalid entries. */\nexport function parsePluginConnections(raw: unknown): PluginConnectionRequirement[] {\n if (!Array.isArray(raw)) return []\n const out: PluginConnectionRequirement[] = []\n const seen = new Set<string>()\n for (const item of raw) {\n if (!item || typeof item !== 'object') continue\n const o = item as Record<string, unknown>\n const id = typeof o.id === 'string' ? o.id.trim().toLowerCase() : ''\n if (!id || !CONNECTION_ID_RE.test(id) || seen.has(id)) continue\n const providerRaw = typeof o.provider === 'string' ? o.provider.trim().toLowerCase() : ''\n if (!isExternalConnectionProvider(providerRaw)) continue\n const scopesRaw = o.scopes\n if (!Array.isArray(scopesRaw) || scopesRaw.length === 0 || scopesRaw.length > MAX_SCOPES) continue\n const scopes: string[] = []\n for (const s of scopesRaw) {\n if (typeof s !== 'string') continue\n const t = s.trim()\n if (!t || t.length > MAX_SCOPE_LEN) continue\n if (!scopes.includes(t)) scopes.push(t)\n }\n if (!scopes.length) continue\n const apisRaw = o.allowed_apis ?? o.allowedApis\n if (!Array.isArray(apisRaw) || apisRaw.length === 0 || apisRaw.length > MAX_ALLOWED_APIS) continue\n const allowed_apis: AllowedApiRule[] = []\n for (const a of apisRaw) {\n const rule = parseAllowedApi(a, providerRaw)\n if (rule) allowed_apis.push(rule)\n }\n if (!allowed_apis.length) continue\n seen.add(id)\n out.push({\n id,\n provider: providerRaw,\n consent: 'user',\n scopes,\n allowed_apis,\n })\n }\n return out\n}\n","import type JSZip from 'jszip'\nimport {\n MAX_PLUGIN_UNCOMPRESSED_BYTES,\n MAX_PLUGIN_ZIP_BYTES,\n MAX_PLUGIN_ZIP_ENTRIES,\n type PluginActionResult,\n} from './types.js'\n\n/** Max uncompressed/compressed ratio per entry (zip-bomb heuristic). */\nexport const MAX_PLUGIN_COMPRESSION_RATIO = 100\n\n/**\n * Validates a loaded plugin ZIP before any entry is inflated (CERVIO-SEC-014):\n * caps the entry count and total declared uncompressed size to stop zip bombs,\n * rejects nested archives, and rejects path-traversal / absolute entry names.\n */\nexport function assertZipSafe(zip: JSZip): PluginActionResult<true> {\n const names = Object.keys(zip.files)\n if (names.length > MAX_PLUGIN_ZIP_ENTRIES) {\n return { ok: false, error: 'zip_too_many_entries' }\n }\n let totalUncompressed = 0\n for (const name of names) {\n if (name.includes('..') || name.includes('\\\\') || name.startsWith('/')) {\n return { ok: false, error: 'zip_unsafe_entry_path' }\n }\n // Nested archives are a classic zip-bomb layering vector.\n if (/\\.zip$/i.test(name) && !zip.files[name]?.dir) {\n return { ok: false, error: 'zip_nested_archive' }\n }\n const entry = zip.files[name] as JSZip.JSZipObject & {\n _data?: { uncompressedSize?: number; compressedSize?: number }\n }\n const uncompressed = entry._data?.uncompressedSize ?? 0\n const compressed = entry._data?.compressedSize ?? 0\n totalUncompressed += uncompressed\n if (totalUncompressed > MAX_PLUGIN_UNCOMPRESSED_BYTES) {\n return { ok: false, error: 'zip_uncompressed_too_large' }\n }\n if (compressed > 0 && uncompressed > 1024 * 1024) {\n const ratio = uncompressed / compressed\n if (ratio > MAX_PLUGIN_COMPRESSION_RATIO) {\n return { ok: false, error: 'zip_compression_ratio_too_high' }\n }\n } else if (compressed === 0 && uncompressed > 1024 * 1024) {\n return { ok: false, error: 'zip_compression_ratio_too_high' }\n }\n }\n return { ok: true, value: true }\n}\n\nexport function assertZipFile(file: { name?: string; size: number }): PluginActionResult<true> {\n const name = (file.name ?? 'upload.zip').toLowerCase()\n if (!name.endsWith('.zip')) return { ok: false, error: 'invalid_file_extension' }\n if (file.size <= 0) return { ok: false, error: 'empty_file' }\n if (file.size > MAX_PLUGIN_ZIP_BYTES) return { ok: false, error: 'file_too_large' }\n return { ok: true, value: true }\n}\n","const CORE_SEMVER_RE = /^(\\d+)\\.(\\d+)\\.(\\d+)/\n\n/**\n * Next patch version assigned by Cervio. Ignores pre-release/build metadata on\n * the previous label and bumps the patch component only.\n */\nexport function nextPatchVersion(latest: string | null | undefined): string {\n if (!latest || typeof latest !== 'string') return '0.1.0'\n const m = latest.trim().match(CORE_SEMVER_RE)\n if (!m) return '0.1.0'\n const major = Number(m[1])\n const minor = Number(m[2])\n const patch = Number(m[3])\n if (![major, minor, patch].every((n) => Number.isFinite(n) && n >= 0)) return '0.1.0'\n return `${major}.${minor}.${patch + 1}`\n}\n\n/** Compare core x.y.z numerically (descending sort helper). */\nexport function compareSemverDesc(a: string, b: string): number {\n const pa = a.match(CORE_SEMVER_RE)\n const pb = b.match(CORE_SEMVER_RE)\n if (!pa && !pb) return 0\n if (!pa) return 1\n if (!pb) return -1\n for (let i = 1; i <= 3; i++) {\n const da = Number(pa[i]) - Number(pb[i])\n if (da !== 0) return da > 0 ? -1 : 1\n }\n return 0\n}\n","import { z } from 'zod'\n\n/** Zod schema documenting the author-facing manifest shape (source of truth for JSON Schema). */\nexport const pluginManifestZodSchema = z\n .object({\n plugin_key: z\n .string()\n .regex(/^[a-z0-9][a-z0-9-_]{1,62}$/)\n .optional()\n .describe('Stable plugin id. Prefer this over legacy `id`.'),\n id: z.string().optional().describe('Legacy alias for plugin_key (slashes become dashes).'),\n plugin_name: z.string().optional(),\n name: z.string().optional().describe('Legacy alias for plugin_name.'),\n plugin_type: z\n .enum(['task', 'form', 'task_form', 'route', 'policy', 'server'])\n .optional()\n .describe('Use `policy` for Policy Plugins. `server` is a legacy alias for `policy`.'),\n kind: z\n .string()\n .optional()\n .describe('Legacy alias for plugin_type (task_widget→task, record_panel→form).'),\n version: z\n .string()\n .optional()\n .describe('Ignored by Cervio - the host assigns release versions.'),\n hooks: z\n .array(\n z.object({\n event: z.enum(['before_create', 'before_update']),\n entities: z.array(z.string()).optional(),\n blocking: z.boolean().optional(),\n identity: z.enum(['caller', 'plugin_principal']).optional(),\n entry: z.string().optional(),\n }),\n )\n .optional()\n .describe('Policy Plugin hook declarations (plugin_type=policy; legacy server).'),\n\n required_connection_capabilities: z.array(z.string()).optional(),\n requiredConnectionCapabilities: z.array(z.string()).optional(),\n connections: z\n .array(\n z.object({\n id: z.string(),\n provider: z.string(),\n scopes: z.array(z.string()),\n allowed_apis: z\n .array(\n z.object({\n host: z.string(),\n methods: z.array(z.string()),\n path_prefix: z.string().optional(),\n pathPrefix: z.string().optional(),\n }),\n )\n .optional(),\n allowedApis: z.array(z.unknown()).optional(),\n }),\n )\n .optional(),\n entities: z\n .array(\n z.object({\n name: z.string(),\n fields: z.array(z.string()).optional(),\n forms: z.array(z.string()).optional(),\n access: z.array(z.enum(['read', 'write'])).optional(),\n }),\n )\n .optional(),\n cervio_apis: z\n .array(\n z.object({\n method: z.string().optional(),\n path_prefix: z.string().optional(),\n pathPrefix: z.string().optional(),\n }),\n )\n .optional(),\n cervioApis: z.array(z.unknown()).optional(),\n settings: z\n .array(\n z.object({\n key: z.string(),\n type: z.enum(['string', 'boolean', 'select', 'multiselect']),\n label: z.string(),\n hint: z.string().optional(),\n placeholder: z.string().optional(),\n default: z.union([z.string(), z.boolean(), z.array(z.string())]).optional(),\n options: z\n .array(\n z.object({\n value: z.string(),\n label: z.string(),\n }),\n )\n .optional()\n .describe('Required for `select` / `multiselect`.'),\n }),\n )\n .optional()\n .describe('Admin-editable settings fields (drives Impostazioni dynamic form).'),\n })\n .passthrough()\n\nexport type PluginManifestZod = z.infer<typeof pluginManifestZodSchema>\n","/**\n * Policy Plugin hook contract (shared by host, SDK, and manifest authors).\n * Wire legacy: `plugin_type: \"server\"` is an alias for `\"policy\"`.\n */\n\nexport type PolicyHookEvent = 'before_create' | 'before_update'\n\nexport type PolicyHookCaller = {\n userId?: string\n channel?: string\n organizationId?: string\n}\n\nexport type PolicyHookInput = {\n event: PolicyHookEvent\n entity: {\n id?: string\n name?: string\n }\n record: {\n id?: string | null\n data: Record<string, unknown>\n previousData?: Record<string, unknown> | null\n }\n caller?: PolicyHookCaller\n settings?: Record<string, unknown>\n pluginKey?: string\n allowedEntityReads?: string[]\n deadlineMs?: number\n}\n\nexport type PolicyHookResult =\n | { allow: true }\n | { allow: false; message: string; code?: string }\n\n/** Host-mediated reads injected by plugin-sandbox-runner (null if no allowlist/caller). */\nexport type PolicyHost = {\n getRecord(\n entityName: string,\n id: string,\n ): Promise<{ id: string; data: Record<string, unknown> } | null>\n listRecords(\n entityName: string,\n opts?: {\n filters?: Record<string, unknown>\n limit?: number\n offset?: number\n },\n ): Promise<Array<{ id: string; data: Record<string, unknown> }>>\n sumField(\n entityName: string,\n fieldName: string,\n opts?: { filters?: Record<string, unknown> },\n ): Promise<number>\n}\n\n/** True for canonical `policy` and legacy wire `server`. */\nexport function isPolicyPluginType(t: string | null | undefined): boolean {\n return t === 'policy' || t === 'server'\n}\n\n/** Canonical type written on upload / preferred in new manifests. */\nexport function normalizeToPolicyPluginType(\n t: string | null | undefined,\n): 'policy' | null {\n return isPolicyPluginType(t) ? 'policy' : null\n}\n","/**\n * Policy Plugin isolate loads the entry as a single data: ESM module.\n * Bare npm imports (e.g. `@cervio/policy-plugin-sdk`) will fail at runtime even\n * if `cervio pack` previously succeeded. Detect them before upload.\n */\nconst BARE_IMPORT_RE =\n /(?:from|import)\\s*\\(\\s*['\"](?![./]|data:)([^'\"]+)['\"]\\s*\\)|(?:from|import)\\s+['\"](?![./]|data:)([^'\"]+)['\"]/g\n\nexport function findBareModuleSpecifiers(source: string): string[] {\n const found = new Set<string>()\n for (const match of source.matchAll(BARE_IMPORT_RE)) {\n const spec = (match[1] || match[2] || '').trim()\n if (spec) found.add(spec)\n }\n return [...found]\n}\n\nexport function assertPolicyEntrySelfContained(\n source: string,\n): { ok: true } | { ok: false; error: string; specifiers: string[] } {\n const specifiers = findBareModuleSpecifiers(source)\n if (specifiers.length === 0) return { ok: true }\n return {\n ok: false,\n error: 'policy_entry_not_self_contained',\n specifiers,\n }\n}\n","import JSZip from 'jszip'\nimport { parsePluginConnections } from './connections.js'\nimport {\n parsePluginCervioApiRequirements,\n parsePluginEntityRequirements,\n} from './entity-requirements.js'\nimport { parsePluginSettingsRequirements } from './settings-requirements.js'\nimport {\n DEFAULT_PLUGIN_DECLARABLE_CAPABILITIES,\n PLUGIN_KEY_RE,\n type ParseManifestOptions,\n type ParsedPluginManifest,\n type PluginActionResult,\n type PluginCervioApiRequirement,\n type PluginConnectionRequirement,\n type PluginEntityRequirement,\n type PluginSettingsFieldRequirement,\n type PluginType,\n} from './types.js'\nimport { assertZipSafe } from './zip-safety.js'\nimport { isPolicyPluginType } from './policy-types.js'\nimport { assertPolicyEntrySelfContained } from './policy-entry.js'\n\nexport function normalizePluginKey(raw: string): string {\n return raw\n .trim()\n .toLowerCase()\n .replace(/[\\/\\s]+/g, '-')\n .replace(/[^a-z0-9-_]/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-+|-+$/g, '')\n}\n\nfunction resolvePluginType(raw: string): PluginType | null {\n const kindMap: Record<string, PluginType> = {\n route: 'route',\n task: 'task',\n form: 'form',\n task_form: 'task_form',\n // Legacy wire → canonical Policy Plugin type\n server: 'policy',\n policy: 'policy',\n task_widget: 'task',\n record_panel: 'form',\n }\n const candidate = kindMap[raw] ?? raw\n return (['task', 'form', 'task_form', 'route', 'policy', 'server'] as const).includes(\n candidate as PluginType,\n )\n ? (candidate as PluginType)\n : null\n}\n\nfunction parseRequiredCapabilities(\n raw: unknown,\n allowed: readonly string[],\n): string[] {\n if (!Array.isArray(raw)) return []\n const allowedSet = new Set(allowed)\n const out: string[] = []\n const seen = new Set<string>()\n for (const item of raw) {\n if (typeof item !== 'string') continue\n const id = item.trim().toLowerCase()\n if (!id || !allowedSet.has(id) || seen.has(id)) continue\n seen.add(id)\n out.push(id)\n }\n return out\n}\n\nexport function parseManifestObject(\n parsed: Record<string, unknown>,\n options?: ParseManifestOptions,\n): PluginActionResult<{\n pluginKey: string\n pluginName: string | null\n pluginType: PluginType | null\n manifestVersion: string | null\n requiredConnectionCapabilities: string[]\n connections: PluginConnectionRequirement[]\n entities: PluginEntityRequirement[]\n cervioApis: PluginCervioApiRequirement[]\n settings: PluginSettingsFieldRequirement[]\n}> {\n const allowedCapabilities =\n options?.allowedCapabilities ?? DEFAULT_PLUGIN_DECLARABLE_CAPABILITIES\n\n const pluginKeyRaw =\n typeof parsed.plugin_key === 'string'\n ? parsed.plugin_key\n : typeof parsed.id === 'string'\n ? parsed.id.split('/').filter(Boolean).join('-')\n : ''\n const pluginKey = normalizePluginKey(pluginKeyRaw)\n if (!pluginKey || !PLUGIN_KEY_RE.test(pluginKey)) {\n return { ok: false, error: 'manifest_plugin_key_invalid' }\n }\n const pluginName =\n typeof parsed.plugin_name === 'string' && parsed.plugin_name.trim()\n ? parsed.plugin_name.trim()\n : typeof parsed.name === 'string' && parsed.name.trim()\n ? parsed.name.trim()\n : null\n\n const pluginTypeRaw =\n typeof parsed.plugin_type === 'string'\n ? parsed.plugin_type.trim()\n : typeof parsed.kind === 'string'\n ? parsed.kind.trim()\n : ''\n const pluginType = resolvePluginType(pluginTypeRaw)\n\n const manifestVersion =\n typeof parsed.version === 'string' && parsed.version.trim() ? parsed.version.trim() : null\n\n const requiredRaw =\n parsed.required_connection_capabilities ?? parsed.requiredConnectionCapabilities ?? []\n const requiredConnectionCapabilities = parseRequiredCapabilities(\n requiredRaw,\n allowedCapabilities,\n )\n\n const connections = parsePluginConnections(parsed.connections)\n const entities = parsePluginEntityRequirements(parsed.entities)\n const cervioApis = parsePluginCervioApiRequirements(\n parsed.cervio_apis ?? parsed.cervioApis ?? [],\n )\n const settings = parsePluginSettingsRequirements(parsed.settings)\n\n return {\n ok: true,\n value: {\n pluginKey,\n pluginName,\n pluginType,\n manifestVersion,\n requiredConnectionCapabilities,\n connections,\n entities,\n cervioApis,\n settings,\n },\n }\n}\n\n/** Manifest JSON for hashing: drop author `version` so Cervio-owned labels do not affect dedup. */\nexport function manifestJsonForContentHash(raw: Record<string, unknown>): string {\n const clone: Record<string, unknown> = { ...raw }\n delete clone.version\n return JSON.stringify(clone)\n}\n\nexport async function loadZipFromBuffer(\n buffer: ArrayBuffer | Buffer,\n): Promise<PluginActionResult<JSZip>> {\n try {\n const zip = await JSZip.loadAsync(buffer)\n const safe = assertZipSafe(zip)\n if (!safe.ok) return safe\n return { ok: true, value: zip }\n } catch {\n return { ok: false, error: 'zip_invalid' }\n }\n}\n\nexport async function parseZipManifest(\n file: File | Blob,\n options?: ParseManifestOptions,\n): Promise<PluginActionResult<ParsedPluginManifest>> {\n const buffer = await file.arrayBuffer()\n const zipRes = await loadZipFromBuffer(buffer)\n if (!zipRes.ok) return zipRes\n const zip = zipRes.value\n\n const manifestEntry =\n zip.file('manifest.json') ??\n zip.file('manifest.example.json') ??\n Object.values(zip.files).find(\n (f) => f.name.endsWith('/manifest.json') || f.name.endsWith('/manifest.example.json'),\n )\n if (!manifestEntry) return { ok: false, error: 'manifest_not_found_in_zip' }\n\n const jsonText = await manifestEntry.async('text')\n let parsed: Record<string, unknown>\n try {\n parsed = JSON.parse(jsonText) as Record<string, unknown>\n } catch {\n return { ok: false, error: 'manifest_invalid_json' }\n }\n\n const fields = parseManifestObject(parsed, options)\n if (!fields.ok) return fields\n\n const isPolicy = isPolicyPluginType(fields.value.pluginType)\n if (!isPolicy) {\n const hasDistIndex = !!zip.file('dist/index.html')\n if (!hasDistIndex) return { ok: false, error: 'build_index_missing' }\n const hasDistAssets = Object.keys(zip.files).some((name) => /^dist\\/assets\\/.+/.test(name))\n if (!hasDistAssets) return { ok: false, error: 'build_assets_missing' }\n }\n\n const entryFromHooks =\n isPolicy && Array.isArray(parsed.hooks)\n ? (() => {\n for (const h of parsed.hooks as Array<Record<string, unknown>>) {\n if (typeof h?.entry === 'string' && h.entry.trim()) return h.entry.trim()\n }\n return null\n })()\n : null\n\n const artifactEntryPath = isPolicy ? entryFromHooks || 'server/index.js' : 'dist/index.html'\n\n if (isPolicy) {\n const entryFile =\n zip.file(artifactEntryPath) ||\n zip.file(artifactEntryPath.replace(/^\\//, '')) ||\n Object.values(zip.files).find((f) => f.name.endsWith(`/${artifactEntryPath}`))\n if (!entryFile) return { ok: false, error: 'manifest_not_found_in_zip' }\n const entrySource = await entryFile.async('text')\n const selfContained = assertPolicyEntrySelfContained(entrySource)\n if (!selfContained.ok) {\n return {\n ok: false,\n error: `${selfContained.error}:${selfContained.specifiers.join(',')}`,\n }\n }\n }\n\n return {\n ok: true,\n value: {\n ...fields.value,\n artifactEntryPath,\n rawManifest: parsed,\n manifestEntryName: manifestEntry.name,\n },\n }\n}\n","import { createHash } from 'node:crypto'\nimport type JSZip from 'jszip'\nimport { manifestJsonForContentHash } from './manifest.js'\nimport type { PluginActionResult } from './types.js'\n\n/**\n * Deterministic SHA-256 over:\n * - manifest.json (JSON without `version` field)\n * - every non-directory entry under dist/** (paths sorted)\n *\n * README / other root files and ZIP compression metadata do not affect the hash.\n */\nexport async function computePluginContentSha256(\n zip: JSZip,\n rawManifest: Record<string, unknown>,\n): Promise<PluginActionResult<string>> {\n try {\n const hash = createHash('sha256')\n hash.update('manifest\\0')\n hash.update(manifestJsonForContentHash(rawManifest))\n hash.update('\\0')\n\n const distPaths = Object.keys(zip.files)\n .filter((name) => {\n const entry = zip.files[name]\n if (!entry || entry.dir) return false\n const normalized = name.replace(/^\\.\\//, '')\n return normalized === 'dist' || normalized.startsWith('dist/')\n })\n .map((name) => name.replace(/^\\.\\//, ''))\n .sort((a, b) => a.localeCompare(b))\n\n for (const path of distPaths) {\n const entry = zip.file(path)\n if (!entry || entry.dir) continue\n const bytes = await entry.async('uint8array')\n hash.update('file\\0')\n hash.update(path)\n hash.update('\\0')\n hash.update(bytes)\n hash.update('\\0')\n }\n\n return { ok: true, value: hash.digest('hex') }\n } catch {\n return { ok: false, error: 'content_hash_failed' }\n }\n}\n\nexport function sha256Hex(buffer: Buffer | Uint8Array): string {\n return createHash('sha256').update(buffer).digest('hex')\n}\n","import { promises as fs } from 'node:fs'\nimport path from 'node:path'\nimport JSZip from 'jszip'\nimport { computePluginContentSha256 } from './content-hash.js'\nimport { loadZipFromBuffer, parseManifestObject, parseZipManifest } from './manifest.js'\nimport { isPolicyPluginType } from './policy-types.js'\nimport { assertPolicyEntrySelfContained } from './policy-entry.js'\nimport type { ParseManifestOptions, PluginActionResult } from './types.js'\nimport { assertZipFile, assertZipSafe } from './zip-safety.js'\n\nexport type PackPluginResult = {\n buffer: Buffer\n pluginKey: string\n contentSha256: string\n sizeBytes: number\n}\n\nasync function collectFiles(dir: string, base = ''): Promise<Array<{ rel: string; abs: string }>> {\n const entries = await fs.readdir(dir, { withFileTypes: true })\n const out: Array<{ rel: string; abs: string }> = []\n for (const entry of entries) {\n const abs = path.join(dir, entry.name)\n const rel = base ? `${base}/${entry.name}` : entry.name\n if (entry.isDirectory()) {\n out.push(...(await collectFiles(abs, rel)))\n } else if (entry.isFile()) {\n out.push({ rel: rel.replace(/\\\\/g, '/'), abs })\n }\n }\n return out\n}\n\n/**\n * Pack a built plugin directory into a ZIP buffer.\n * Expects `manifest.json` at root and `dist/index.html` + `dist/assets/*`.\n */\nexport async function packPlugin(opts: {\n dir: string\n options?: ParseManifestOptions\n}): Promise<PluginActionResult<PackPluginResult>> {\n const root = path.resolve(opts.dir)\n const manifestPath = path.join(root, 'manifest.json')\n let manifestRaw: Record<string, unknown>\n try {\n const text = await fs.readFile(manifestPath, 'utf8')\n manifestRaw = JSON.parse(text) as Record<string, unknown>\n } catch {\n return { ok: false, error: 'manifest_not_found_in_zip' }\n }\n\n const fields = parseManifestObject(manifestRaw, opts.options)\n if (!fields.ok) return fields\n\n const isPolicy = isPolicyPluginType(fields.value.pluginType)\n if (!isPolicy) {\n const distIndex = path.join(root, 'dist', 'index.html')\n try {\n await fs.access(distIndex)\n } catch {\n return { ok: false, error: 'build_index_missing' }\n }\n } else {\n const entry =\n (Array.isArray(manifestRaw.hooks)\n ? (manifestRaw.hooks as Array<{ entry?: string }>).find((h) => h?.entry)?.entry\n : null) || 'server/index.js'\n const entryAbs = path.join(root, entry)\n try {\n await fs.access(entryAbs)\n } catch {\n return { ok: false, error: 'manifest_not_found_in_zip' }\n }\n let entrySource: string\n try {\n entrySource = await fs.readFile(entryAbs, 'utf8')\n } catch {\n return { ok: false, error: 'manifest_not_found_in_zip' }\n }\n const selfContained = assertPolicyEntrySelfContained(entrySource)\n if (!selfContained.ok) {\n return {\n ok: false,\n error: `${selfContained.error}:${selfContained.specifiers.join(',')}`,\n }\n }\n }\n\n const zip = new JSZip()\n const files = await collectFiles(root)\n let hasAssets = false\n for (const file of files) {\n if (file.rel.startsWith('.cervio/') || file.rel === 'node_modules' || file.rel.startsWith('node_modules/')) {\n continue\n }\n if (file.rel.startsWith('dist/assets/') && file.rel !== 'dist/assets/') {\n hasAssets = true\n }\n const data = await fs.readFile(file.abs)\n zip.file(file.rel, data)\n }\n if (!isPolicy && !hasAssets) return { ok: false, error: 'build_assets_missing' }\n\n const safe = assertZipSafe(zip)\n if (!safe.ok) return safe\n\n const buffer = Buffer.from(await zip.generateAsync({ type: 'uint8array', compression: 'DEFLATE' }))\n const fileCheck = assertZipFile({ name: `${fields.value.pluginKey}.zip`, size: buffer.length })\n if (!fileCheck.ok) return fileCheck\n\n const loaded = await loadZipFromBuffer(buffer)\n if (!loaded.ok) return loaded\n const hash = await computePluginContentSha256(loaded.value, manifestRaw)\n if (!hash.ok) return hash\n\n return {\n ok: true,\n value: {\n buffer,\n pluginKey: fields.value.pluginKey,\n contentSha256: hash.value,\n sizeBytes: buffer.length,\n },\n }\n}\n\n/** Validate an on-disk plugin directory (or an existing ZIP) without uploading. */\nexport async function validatePluginDir(\n dir: string,\n options?: ParseManifestOptions,\n): Promise<PluginActionResult<{ pluginKey: string; contentSha256: string }>> {\n const packed = await packPlugin({ dir, options })\n if (!packed.ok) return packed\n const blob = new Blob([packed.value.buffer], { type: 'application/zip' })\n const parsed = await parseZipManifest(blob, options)\n if (!parsed.ok) return parsed\n return {\n ok: true,\n value: {\n pluginKey: packed.value.pluginKey,\n contentSha256: packed.value.contentSha256,\n },\n }\n}\n\nexport async function validatePluginZipBuffer(\n buffer: Buffer,\n options?: ParseManifestOptions,\n): Promise<PluginActionResult<{ pluginKey: string; contentSha256: string }>> {\n const fileCheck = assertZipFile({ name: 'plugin.zip', size: buffer.length })\n if (!fileCheck.ok) return fileCheck\n const blob = new Blob([buffer], { type: 'application/zip' })\n const parsed = await parseZipManifest(blob, options)\n if (!parsed.ok) return parsed\n const zipRes = await loadZipFromBuffer(buffer)\n if (!zipRes.ok) return zipRes\n const hash = await computePluginContentSha256(zipRes.value, parsed.value.rawManifest)\n if (!hash.ok) return hash\n return {\n ok: true,\n value: { pluginKey: parsed.value.pluginKey, contentSha256: hash.value },\n }\n}\n"]}