@clowder-ai/plugin-contract 0.1.0-beta.12 → 0.1.0-beta.13

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.
@@ -0,0 +1,140 @@
1
+ import { createRequire } from 'node:module';
2
+ const require = createRequire(import.meta.url);
3
+ const Ajv2020 = require('ajv/dist/2020');
4
+ const addFormats = require('ajv-formats');
5
+ const pluginMetadataSchema = require('@clowder-ai/plugin-contract/schemas/plugin-metadata');
6
+ const catalogSchema = require('@clowder-ai/plugin-contract/schemas/catalog');
7
+ const ajv = new Ajv2020({ allErrors: true, strict: false });
8
+ addFormats(ajv);
9
+ ajv.addSchema(pluginMetadataSchema, pluginMetadataSchema['$id']);
10
+ const validateSchema = ajv.compile(catalogSchema);
11
+ function semanticError(instancePath, schemaPath, keyword, message) {
12
+ return { valid: false, errors: [{ instancePath, schemaPath, keyword, message }] };
13
+ }
14
+ function parseSemVer(value) {
15
+ const buildIndex = value.indexOf('+');
16
+ const withoutBuild = buildIndex === -1 ? value : value.slice(0, buildIndex);
17
+ const prereleaseIndex = withoutBuild.indexOf('-');
18
+ const core = prereleaseIndex === -1 ? withoutBuild : withoutBuild.slice(0, prereleaseIndex);
19
+ const prerelease = prereleaseIndex === -1 ? '' : withoutBuild.slice(prereleaseIndex + 1);
20
+ const [major, minor, patch] = core.split('.');
21
+ return {
22
+ numbers: [major, minor, patch],
23
+ prerelease: prerelease === '' ? [] : prerelease.split('.'),
24
+ };
25
+ }
26
+ function compareAscii(left, right) {
27
+ return left < right ? -1 : left > right ? 1 : 0;
28
+ }
29
+ function compareNumericIdentifier(left, right) {
30
+ const lengthDelta = left.length - right.length;
31
+ return lengthDelta === 0 ? compareAscii(left, right) : lengthDelta;
32
+ }
33
+ function compareSemVer(left, right) {
34
+ const a = parseSemVer(left);
35
+ const b = parseSemVer(right);
36
+ for (let index = 0; index < a.numbers.length; index += 1) {
37
+ const delta = compareNumericIdentifier(a.numbers[index], b.numbers[index]);
38
+ if (delta !== 0)
39
+ return delta;
40
+ }
41
+ if (a.prerelease.length === 0 || b.prerelease.length === 0) {
42
+ return a.prerelease.length === b.prerelease.length ? 0 : a.prerelease.length === 0 ? 1 : -1;
43
+ }
44
+ const length = Math.max(a.prerelease.length, b.prerelease.length);
45
+ for (let index = 0; index < length; index += 1) {
46
+ const aPart = a.prerelease[index];
47
+ const bPart = b.prerelease[index];
48
+ if (aPart === undefined || bPart === undefined)
49
+ return aPart === undefined ? -1 : 1;
50
+ if (aPart === bPart)
51
+ continue;
52
+ const aNumeric = /^[0-9]+$/.test(aPart);
53
+ const bNumeric = /^[0-9]+$/.test(bPart);
54
+ if (aNumeric && bNumeric)
55
+ return compareNumericIdentifier(aPart, bPart);
56
+ if (aNumeric !== bNumeric)
57
+ return aNumeric ? -1 : 1;
58
+ return compareAscii(aPart, bPart);
59
+ }
60
+ return 0;
61
+ }
62
+ /** Validate repository-owned discovery truth without creating Host inventory state. */
63
+ export function validatePluginCatalog(value) {
64
+ if (!validateSchema(value)) {
65
+ return {
66
+ valid: false,
67
+ errors: (validateSchema.errors ?? []).map((error) => ({
68
+ instancePath: error.instancePath,
69
+ schemaPath: error.schemaPath,
70
+ keyword: error.keyword,
71
+ message: error.message ?? 'catalog validation failed',
72
+ })),
73
+ };
74
+ }
75
+ const catalog = value;
76
+ const pluginIds = new Set();
77
+ let priorPluginId;
78
+ for (const [pluginIndex, plugin] of catalog.plugins.entries()) {
79
+ if (pluginIds.has(plugin.pluginId)) {
80
+ return semanticError(`/plugins/${pluginIndex}/pluginId`, '#/$defs/CatalogPluginEntry/uniquePluginIds', 'uniquePluginIds', 'pluginId must be declared at most once per catalog');
81
+ }
82
+ if (priorPluginId !== undefined && compareAscii(priorPluginId, plugin.pluginId) >= 0) {
83
+ return semanticError(`/plugins/${pluginIndex}/pluginId`, '#/properties/plugins/deterministicOrder', 'deterministicOrder', 'catalog plugins must be sorted by pluginId');
84
+ }
85
+ pluginIds.add(plugin.pluginId);
86
+ priorPluginId = plugin.pluginId;
87
+ let priorKeyword;
88
+ for (const [keywordIndex, keyword] of (plugin.keywords ?? []).entries()) {
89
+ if (priorKeyword !== undefined && compareAscii(priorKeyword, keyword) >= 0) {
90
+ return semanticError(`/plugins/${pluginIndex}/keywords/${keywordIndex}`, '#/$defs/CatalogPluginEntry/deterministicKeywordOrder', 'deterministicKeywordOrder', 'catalog keywords must be unique and sorted by ASCII code point');
91
+ }
92
+ priorKeyword = keyword;
93
+ }
94
+ const versions = new Set();
95
+ let priorVersion;
96
+ for (const [versionIndex, version] of plugin.versions.entries()) {
97
+ if (versions.has(version.version)) {
98
+ return semanticError(`/plugins/${pluginIndex}/versions/${versionIndex}/version`, '#/$defs/CatalogPluginVersion/uniqueVersions', 'uniqueVersions', 'version must be declared at most once per plugin');
99
+ }
100
+ if (version.artifact.version !== version.version) {
101
+ return semanticError(`/plugins/${pluginIndex}/versions/${versionIndex}/artifact/version`, '#/$defs/CatalogPluginVersion/artifactVersionMatches', 'artifactVersionMatches', 'artifact version must exactly match the catalog version');
102
+ }
103
+ const unscopedPackageName = version.artifact.packageName.slice(version.artifact.packageName.indexOf('/') + 1);
104
+ const expectedTarballUrl = `https://registry.npmjs.org/${version.artifact.packageName}/-/` +
105
+ `${unscopedPackageName}-${version.version}.tgz`;
106
+ if (version.artifact.tarballUrl !== expectedTarballUrl) {
107
+ return semanticError(`/plugins/${pluginIndex}/versions/${versionIndex}/artifact/tarballUrl`, '#/$defs/NpmArtifact/packageVersionTarball', 'packageVersionTarball', 'npm tarball URL must exactly match the declared package name and version');
108
+ }
109
+ if (priorVersion !== undefined && compareSemVer(priorVersion, version.version) <= 0) {
110
+ return semanticError(`/plugins/${pluginIndex}/versions/${versionIndex}/version`, '#/$defs/CatalogPluginVersion/descendingOrder', 'descendingOrder', 'catalog versions must be in descending semantic-version order');
111
+ }
112
+ versions.add(version.version);
113
+ priorVersion = version.version;
114
+ }
115
+ }
116
+ return { valid: true, catalog, errors: [] };
117
+ }
118
+ export function listCatalogPlugins(catalog) {
119
+ return catalog.plugins;
120
+ }
121
+ export function searchCatalogPlugins(catalog, query) {
122
+ const normalized = query.trim().toLocaleLowerCase('en-US');
123
+ if (normalized === '')
124
+ return catalog.plugins;
125
+ return catalog.plugins.filter((plugin) => {
126
+ const descriptions = typeof plugin.description === 'string'
127
+ ? [plugin.description]
128
+ : [plugin.description.default, ...Object.values(plugin.description.translations)];
129
+ return [plugin.pluginId, plugin.name, ...descriptions, ...(plugin.keywords ?? [])].some((field) => field.toLocaleLowerCase('en-US').includes(normalized));
130
+ });
131
+ }
132
+ export function getCatalogPlugin(catalog, pluginId, version) {
133
+ const plugin = catalog.plugins.find((entry) => entry.pluginId === pluginId);
134
+ if (plugin === undefined)
135
+ return undefined;
136
+ return version === undefined
137
+ ? plugin.versions[0]
138
+ : plugin.versions.find((entry) => entry.version === version);
139
+ }
140
+ //# sourceMappingURL=catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/validation/catalog.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  export { validateMessagingSemantics, type SemanticValidationError, type SemanticValidationResult, } from './messaging-semantic.js';
2
2
  export { MESSAGING_ROW_METHODS, validateMessagingRowInput, validateMessagingRowResult, type MessagingRowInputByMethod, type MessagingRowMethod, type MessagingRowResultByMethod, type MessagingRowValidationError, type MessagingRowValidationResult, } from './messaging-wire.js';
3
3
  export { validateManifest, type ManifestValidationError, type ManifestValidationResult, } from './manifest.js';
4
+ export { getCatalogPlugin, listCatalogPlugins, searchCatalogPlugins, validatePluginCatalog, type CatalogValidationError, type CatalogValidationResult, } from './catalog.js';
4
5
  export { SIGNAL_PAYLOAD_MAX_ENCODED_BYTES, validateDeclaredEventsPublishInput, validateEventsPublishInput, validateEventsPublishResult, validateSignalDeclaration, type SignalSchemaCatalog, type SignalValidationError, type SignalValidationResult, } from './signals.js';
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/validation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,EAC1B,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,GAC9B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,0BAA0B,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,kBAAkB,EACvB,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,EAChC,KAAK,4BAA4B,GAClC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,GAC9B,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,gCAAgC,EAChC,kCAAkC,EAClC,0BAA0B,EAC1B,2BAA2B,EAC3B,yBAAyB,EACzB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,GAC5B,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/validation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,EAC1B,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,GAC9B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,0BAA0B,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,kBAAkB,EACvB,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,EAChC,KAAK,4BAA4B,GAClC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,GAC9B,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,EACpB,qBAAqB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,GAC7B,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,gCAAgC,EAChC,kCAAkC,EAClC,0BAA0B,EAC1B,2BAA2B,EAC3B,yBAAyB,EACzB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,GAC5B,MAAM,cAAc,CAAC"}
@@ -1,5 +1,6 @@
1
1
  export { validateMessagingSemantics, } from './messaging-semantic.js';
2
2
  export { MESSAGING_ROW_METHODS, validateMessagingRowInput, validateMessagingRowResult, } from './messaging-wire.js';
3
3
  export { validateManifest, } from './manifest.js';
4
+ export { getCatalogPlugin, listCatalogPlugins, searchCatalogPlugins, validatePluginCatalog, } from './catalog.js';
4
5
  export { SIGNAL_PAYLOAD_MAX_ENCODED_BYTES, validateDeclaredEventsPublishInput, validateEventsPublishInput, validateEventsPublishResult, validateSignalDeclaration, } from './signals.js';
5
6
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/validation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,GAG3B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,0BAA0B,GAM3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,gBAAgB,GAGjB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,gCAAgC,EAChC,kCAAkC,EAClC,0BAA0B,EAC1B,2BAA2B,EAC3B,yBAAyB,GAI1B,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/validation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,GAG3B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,0BAA0B,GAM3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,gBAAgB,GAGjB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,oBAAoB,EACpB,qBAAqB,GAGtB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,gCAAgC,EAChC,kCAAkC,EAClC,0BAA0B,EAC1B,2BAA2B,EAC3B,yBAAyB,GAI1B,MAAM,cAAc,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/validation/manifest.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAkCzE,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,MAAM,wBAAwB,GAChC;IACE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC;CAC9B,GACD;IACE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,SAAS,uBAAuB,EAAE,CAAC;CACrD,CAAC;AAON;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,wBAAwB,CAoCzE"}
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/validation/manifest.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAqCzE,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,MAAM,wBAAwB,GAChC;IACE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC;CAC9B,GACD;IACE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,SAAS,uBAAuB,EAAE,CAAC;CACrD,CAAC;AAoBN;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,wBAAwB,CAwNzE"}
@@ -2,12 +2,20 @@ import { createRequire } from 'node:module';
2
2
  const require = createRequire(import.meta.url);
3
3
  const Ajv2020 = require('ajv/dist/2020');
4
4
  const addFormats = require('ajv-formats');
5
+ const pluginMetadataSchema = require('@clowder-ai/plugin-contract/schemas/plugin-metadata');
5
6
  const manifestSchema = require('@clowder-ai/plugin-contract/schemas/manifest');
6
7
  const signalSchema = require('@clowder-ai/plugin-contract/schemas/signals');
7
8
  const ajv = new Ajv2020({ allErrors: true, strict: false });
8
9
  addFormats(ajv);
10
+ ajv.addSchema(pluginMetadataSchema, pluginMetadataSchema['$id']);
9
11
  ajv.addSchema(signalSchema, signalSchema['$id']);
10
12
  const validateSchema = ajv.compile(manifestSchema);
13
+ function semanticError(instancePath, schemaPath, keyword, message) {
14
+ return {
15
+ valid: false,
16
+ errors: [{ instancePath, schemaPath, keyword, message }],
17
+ };
18
+ }
11
19
  /**
12
20
  * Validates an untrusted plugin manifest against the contract-owned schema.
13
21
  *
@@ -34,6 +42,102 @@ export function validateManifest(value) {
34
42
  }
35
43
  declaredTypes.add(declaration.type);
36
44
  }
45
+ const featureIds = new Set();
46
+ for (const [index, feature] of manifest.features.entries()) {
47
+ if (featureIds.has(feature.id)) {
48
+ return semanticError(`/features/${index}/id`, '#/$defs/PluginFeature/uniqueFeatureIds', 'uniqueFeatureIds', 'feature id must be declared at most once per manifest');
49
+ }
50
+ featureIds.add(feature.id);
51
+ }
52
+ const configuration = manifest.configuration ?? [];
53
+ const configByKey = new Map();
54
+ for (const [index, field] of configuration.entries()) {
55
+ if (configByKey.has(field.key)) {
56
+ return semanticError(`/configuration/${index}/key`, '#/$defs/ConfigurationField/uniqueConfigurationKeys', 'uniqueConfigurationKeys', 'configuration key must be declared at most once per manifest');
57
+ }
58
+ configByKey.set(field.key, field);
59
+ if (field.kind === 'select') {
60
+ const optionValues = new Set();
61
+ for (const [optionIndex, option] of (field.options ?? []).entries()) {
62
+ if (optionValues.has(option.value)) {
63
+ return semanticError(`/configuration/${index}/options/${optionIndex}/value`, '#/$defs/ConfigurationOption/uniqueOptionValues', 'uniqueOptionValues', 'select option values must be unique within one configuration field');
64
+ }
65
+ optionValues.add(option.value);
66
+ }
67
+ if (field.default !== undefined && !optionValues.has(field.default)) {
68
+ return semanticError(`/configuration/${index}/default`, '#/$defs/ConfigurationField/defaultDeclaredBySelect', 'defaultDeclaredBySelect', 'select default must equal one of the declared option values');
69
+ }
70
+ }
71
+ }
72
+ const contributions = manifest.contributions ?? [];
73
+ const contributionByKey = new Map();
74
+ for (const [index, contribution] of contributions.entries()) {
75
+ const key = `${contribution.type}\0${contribution.id}`;
76
+ if (contributionByKey.has(key)) {
77
+ return semanticError(`/contributions/${index}/id`, '#/$defs/StaticContribution/uniqueContributionKeys', 'uniqueContributionKeys', 'contribution type/id must be declared at most once per manifest');
78
+ }
79
+ contributionByKey.set(key, contribution);
80
+ if ('environment' in contribution && contribution.environment !== undefined) {
81
+ for (const [environmentName, binding] of Object.entries(contribution.environment)) {
82
+ const field = configByKey.get(binding.key);
83
+ if (field === undefined) {
84
+ return semanticError(`/contributions/${index}/environment/${environmentName}/key`, '#/$defs/EnvironmentBinding/declaredConfigurationKey', 'declaredConfigurationKey', 'environment binding must reference a declared configuration key');
85
+ }
86
+ if ((binding.source === 'secret' && field.kind !== 'secret') ||
87
+ (binding.source === 'config' && field.kind === 'secret')) {
88
+ return semanticError(`/contributions/${index}/environment/${environmentName}/source`, '#/$defs/EnvironmentBinding/sourceMatchesConfigurationKind', 'sourceMatchesConfigurationKind', 'secret bindings must reference secret fields and config bindings must not');
89
+ }
90
+ }
91
+ }
92
+ if (contribution.type === 'webhook' && contribution.verificationSecretRef !== undefined) {
93
+ const secret = configByKey.get(contribution.verificationSecretRef);
94
+ if (secret?.kind !== 'secret') {
95
+ return semanticError(`/contributions/${index}/verificationSecretRef`, '#/$defs/WebhookContribution/declaredSecretReference', 'declaredSecretReference', 'webhook verificationSecretRef must reference a declared secret field');
96
+ }
97
+ }
98
+ }
99
+ const referenceOwners = new Map();
100
+ for (const [featureIndex, feature] of manifest.features.entries()) {
101
+ for (const [contributionIndex, reference] of (feature.contributions ?? []).entries()) {
102
+ const key = `${reference.type}\0${reference.id}`;
103
+ if (!contributionByKey.has(key)) {
104
+ return semanticError(`/features/${featureIndex}/contributions/${contributionIndex}`, '#/$defs/ContributionReference/declaredContribution', 'declaredContribution', 'feature contribution must reference a declared contribution with the same type and id');
105
+ }
106
+ const existingOwner = referenceOwners.get(key);
107
+ if (existingOwner !== undefined) {
108
+ return semanticError(`/features/${featureIndex}/contributions/${contributionIndex}`, '#/$defs/ContributionReference/singleFeatureOwner', 'singleFeatureOwner', `a static contribution must have exactly one feature reference; already owned by ${existingOwner}`);
109
+ }
110
+ referenceOwners.set(key, feature.id);
111
+ }
112
+ }
113
+ for (const [key, contribution] of contributionByKey) {
114
+ if (!referenceOwners.has(key)) {
115
+ const index = contributions.indexOf(contribution);
116
+ return semanticError(`/contributions/${index}`, '#/$defs/StaticContribution/featureOwnerRequired', 'featureOwnerRequired', 'every static contribution must be owned by one feature resource reference');
117
+ }
118
+ }
119
+ for (const [index, contribution] of contributions.entries()) {
120
+ const owner = referenceOwners.get(`${contribution.type}\0${contribution.id}`);
121
+ if (contribution.type === 'connector') {
122
+ const identityKey = `identity\0${contribution.identityRef}`;
123
+ if (!contributionByKey.has(identityKey)) {
124
+ return semanticError(`/contributions/${index}/identityRef`, '#/$defs/ConnectorContribution/declaredIdentityReference', 'declaredIdentityReference', 'connector identityRef must reference a declared identity contribution');
125
+ }
126
+ if (referenceOwners.get(identityKey) !== owner) {
127
+ return semanticError(`/contributions/${index}/identityRef`, '#/$defs/ConnectorContribution/sameFeatureOwner', 'sameFeatureOwner', 'connector identityRef must reference an identity owned by the same feature');
128
+ }
129
+ }
130
+ if (contribution.type === 'ui' && contribution.kind === 'slot-item') {
131
+ const commandKey = `ui\0${contribution.command}`;
132
+ const command = contributionByKey.get(commandKey);
133
+ if (command?.type !== 'ui' || command.kind !== 'command') {
134
+ return semanticError(`/contributions/${index}/command`, '#/$defs/UiSlotItemContribution/declaredCommandReference', 'declaredCommandReference', 'UI slot command must reference a declared UI command contribution');
135
+ }
136
+ if (referenceOwners.get(commandKey) !== owner) {
137
+ return semanticError(`/contributions/${index}/command`, '#/$defs/UiSlotItemContribution/sameFeatureOwner', 'sameFeatureOwner', 'UI slot command must reference a command owned by the same feature');
138
+ }
139
+ }
140
+ }
37
141
  return {
38
142
  valid: true,
39
143
  manifest,
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/validation/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAI5C,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,OAAO,GAGO,OAAO,CAAC,eAAe,CAAC,CAAC;AAC7C,MAAM,UAAU,GAA+B,OAAO,CAAC,aAAa,CAAC,CAAC;AACtE,MAAM,cAAc,GAAG,OAAO,CAAC,8CAA8C,CAG5E,CAAC;AACF,MAAM,YAAY,GAAG,OAAO,CAAC,6CAA6C,CAGzE,CAAC;AAqCF,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;AAC5D,UAAU,CAAC,GAAG,CAAC,CAAC;AAChB,GAAG,CAAC,SAAS,CAAC,YAAY,EAAE,YAAY,CAAC,KAAK,CAAW,CAAC,CAAC;AAC3D,MAAM,cAAc,GAAG,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,IAAI,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,QAAQ,GAAG,KAAuB,CAAC;QACzC,MAAM,aAAa,GAAG,IAAI,GAAG,EAAU,CAAC;QACxC,KAAK,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;YAChF,IAAI,aAAa,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxC,OAAO;oBACL,KAAK,EAAE,KAAK;oBACZ,MAAM,EAAE;wBACN;4BACE,YAAY,EAAE,qBAAqB,KAAK,OAAO;4BAC/C,UAAU,EAAE,8CAA8C;4BAC1D,OAAO,EAAE,mBAAmB;4BAC5B,OAAO,EAAE,wDAAwD;yBAClE;qBACF;iBACF,CAAC;YACJ,CAAC;YACD,aAAa,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACtC,CAAC;QACD,OAAO;YACL,KAAK,EAAE,IAAI;YACX,QAAQ;YACR,MAAM,EAAE,EAAE;SACX,CAAC;IACJ,CAAC;IAED,OAAO;QACL,KAAK,EAAE,KAAK;QACZ,MAAM,EAAE,CAAC,cAAc,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACpD,YAAY,EAAE,KAAK,CAAC,YAAY;YAChC,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,4BAA4B;SACvD,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/validation/manifest.ts"],"names":[],"mappings":"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"}
@@ -14,7 +14,7 @@
14
14
  import type { Capability } from '../generated/contract.generated.js';
15
15
  /**
16
16
  * Maximum number of items in effectiveGrants.
17
- * Derived from the 17-value Capability enum — a plugin cannot hold
17
+ * Derived from the signed 17-value M0 Capability enum — a plugin cannot hold
18
18
  * more capabilities than exist.
19
19
  */
20
20
  export declare const MAX_GRANT_ITEMS: 17;
@@ -17,7 +17,7 @@ import { L0_CAPABILITIES, L1_CAPABILITIES, L2_CAPABILITIES, } from '../generated
17
17
  // ---------------------------------------------------------------------------
18
18
  /**
19
19
  * Maximum number of items in effectiveGrants.
20
- * Derived from the 17-value Capability enum — a plugin cannot hold
20
+ * Derived from the signed 17-value M0 Capability enum — a plugin cannot hold
21
21
  * more capabilities than exist.
22
22
  */
23
23
  export const MAX_GRANT_ITEMS = 17;
@@ -0,0 +1,22 @@
1
+ {
2
+ "pluginId": "com.example.icon-escape",
3
+ "version": "1.0.0",
4
+ "contractVersion": "0.1.0-beta.13",
5
+ "name": "Icon escape fixture",
6
+ "description": "Legacy description remains accepted.",
7
+ "icon": {
8
+ "type": "svg",
9
+ "src": "../outside.svg"
10
+ },
11
+ "features": [
12
+ {
13
+ "id": "main",
14
+ "name": "Main",
15
+ "resources": [],
16
+ "capabilities": []
17
+ }
18
+ ],
19
+ "runtime": {
20
+ "transport": "builtin"
21
+ }
22
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "pluginId": "com.example.localized-metadata",
3
+ "version": "1.0.0",
4
+ "contractVersion": "0.1.0-beta.13",
5
+ "name": "Localized metadata fixture",
6
+ "description": {
7
+ "default": "Describe this plugin for agents and people.",
8
+ "translations": {
9
+ "zh-CN": "向 Agent 和用户介绍这个插件。"
10
+ }
11
+ },
12
+ "icon": {
13
+ "type": "svg",
14
+ "src": "assets/icon.svg"
15
+ },
16
+ "features": [
17
+ {
18
+ "id": "main",
19
+ "name": "Main",
20
+ "resources": [],
21
+ "capabilities": []
22
+ }
23
+ ],
24
+ "runtime": {
25
+ "transport": "builtin"
26
+ }
27
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clowder-ai/plugin-contract",
3
- "version": "0.1.0-beta.12",
3
+ "version": "0.1.0-beta.13",
4
4
  "private": false,
5
5
  "description": "Clowder AI plugin contract — the single machine-readable truth source for plugin schema, types, capability table, and conformance fixtures (P15)",
6
6
  "license": "MIT",
@@ -16,6 +16,8 @@
16
16
  },
17
17
  "./schemas/messaging": "./src/schemas/messaging.schema.json",
18
18
  "./schemas/manifest": "./src/schemas/manifest.schema.json",
19
+ "./schemas/catalog": "./src/schemas/catalog.schema.json",
20
+ "./schemas/plugin-metadata": "./src/schemas/plugin-metadata.schema.json",
19
21
  "./schemas/signals": "./src/schemas/signal.schema.json",
20
22
  "./schemas/physical-limb": "./src/schemas/physical-limb.schema.json",
21
23
  "./schemas/behavior-fixture": "./src/schemas/behavior-fixture.schema.json",
@@ -0,0 +1,91 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://clowder-ai.dev/schemas/catalog/v1",
4
+ "title": "Clowder AI Plugin Catalog (v1)",
5
+ "description": "Repository-owned immutable discovery coordinates. Installed/configured/enabled/live state is deliberately absent because it belongs to the local Host inventory.",
6
+ "$defs": {
7
+ "CatalogSemVer": {
8
+ "type": "string",
9
+ "minLength": 1,
10
+ "pattern": "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(-(0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(\\.(0|[1-9][0-9]*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*)?(\\+[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?$"
11
+ },
12
+ "CatalogPublisher": {
13
+ "type": "object",
14
+ "properties": {
15
+ "id": { "type": "string", "minLength": 1 },
16
+ "name": { "type": "string", "minLength": 1 }
17
+ },
18
+ "required": ["id", "name"],
19
+ "additionalProperties": false
20
+ },
21
+ "ArtifactProvenance": {
22
+ "type": "object",
23
+ "properties": {
24
+ "repository": { "type": "string", "format": "uri", "pattern": "^https://" },
25
+ "sourceDirectory": { "type": "string", "pattern": "^packages/[a-z0-9-]+$" }
26
+ },
27
+ "required": ["repository", "sourceDirectory"],
28
+ "additionalProperties": false
29
+ },
30
+ "NpmArtifact": {
31
+ "type": "object",
32
+ "properties": {
33
+ "kind": { "const": "npm" },
34
+ "packageName": {
35
+ "type": "string",
36
+ "pattern": "^@[a-z0-9][a-z0-9._-]*/[a-z0-9][a-z0-9._-]*$"
37
+ },
38
+ "version": { "$ref": "#/$defs/CatalogSemVer" },
39
+ "tarballUrl": { "type": "string", "format": "uri", "pattern": "^https://registry\\.npmjs\\.org/" },
40
+ "integrity": { "type": "string", "pattern": "^sha512-[A-Za-z0-9+/]{86}==$" },
41
+ "shasum": { "type": "string", "pattern": "^[0-9a-f]{40}$" },
42
+ "provenance": { "$ref": "#/$defs/ArtifactProvenance" }
43
+ },
44
+ "required": ["kind", "packageName", "version", "tarballUrl", "integrity", "shasum", "provenance"],
45
+ "additionalProperties": false
46
+ },
47
+ "CatalogPluginVersion": {
48
+ "type": "object",
49
+ "properties": {
50
+ "version": { "$ref": "#/$defs/CatalogSemVer" },
51
+ "contractVersion": { "$ref": "#/$defs/CatalogSemVer" },
52
+ "manifestPath": { "const": "plugin.yaml" },
53
+ "artifact": { "$ref": "#/$defs/NpmArtifact" }
54
+ },
55
+ "required": ["version", "contractVersion", "manifestPath", "artifact"],
56
+ "additionalProperties": false
57
+ },
58
+ "CatalogPluginEntry": {
59
+ "type": "object",
60
+ "properties": {
61
+ "pluginId": { "type": "string", "minLength": 1 },
62
+ "name": { "type": "string", "minLength": 1 },
63
+ "description": { "$ref": "https://clowder-ai.dev/schemas/plugin-metadata/v1#/$defs/LocalizedDescription" },
64
+ "icon": { "$ref": "https://clowder-ai.dev/schemas/plugin-metadata/v1#/$defs/PluginIcon" },
65
+ "publisher": { "$ref": "#/$defs/CatalogPublisher" },
66
+ "keywords": {
67
+ "type": "array",
68
+ "items": { "type": "string", "minLength": 1 },
69
+ "uniqueItems": true
70
+ },
71
+ "versions": {
72
+ "type": "array",
73
+ "items": { "$ref": "#/$defs/CatalogPluginVersion" },
74
+ "minItems": 1
75
+ }
76
+ },
77
+ "required": ["pluginId", "name", "description", "icon", "publisher", "versions"],
78
+ "additionalProperties": false
79
+ }
80
+ },
81
+ "type": "object",
82
+ "properties": {
83
+ "schemaVersion": { "const": "1" },
84
+ "plugins": {
85
+ "type": "array",
86
+ "items": { "$ref": "#/$defs/CatalogPluginEntry" }
87
+ }
88
+ },
89
+ "required": ["schemaVersion", "plugins"],
90
+ "additionalProperties": false
91
+ }