@ekanos/integration-schema 0.1.0 → 0.1.2
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.d.ts
CHANGED
|
@@ -22,5 +22,6 @@ export type { ComponentReference } from './component-reference.js';
|
|
|
22
22
|
export { isComponentReference } from './component-reference.js';
|
|
23
23
|
export { DNS_NAMESPACE, EKANOS_INTEGRATION_NAMESPACE, derivePlanId, deriveProductId, uuidv5, } from './product-id.js';
|
|
24
24
|
export { WorkspaceTargetSchema, WorkspaceTargetListSchema, WorkspaceTargetSlugSchema, WorkspaceTargetLayoutSchema, createWorkspaceTargetSchema, createWorkspaceTargetListSchema, normalizeWorkspaceTargets, type WorkspaceTargetSchemaOptions, type WorkspaceTargetDefinition, type ResolvedWorkspaceTarget, } from './workspace-target.js';
|
|
25
|
-
export { IntegrationDefinitionSchema, parseIntegrationDefinition, validateIntegrationDefinitions, getDiscoveredToolName, assertPlainDeclaration, deepFreezeDefinition, } from './integration-definition.js';
|
|
25
|
+
export { IntegrationDefinitionSchema, parseIntegrationDefinition, validateIntegrationDefinitions, collectDefinitionFindings, collectCollisionFindings, getDiscoveredToolName, assertPlainDeclaration, deepFreezeDefinition, } from './integration-definition.js';
|
|
26
|
+
export type { Finding, CollectDefinitionOptions, } from './integration-definition.js';
|
|
26
27
|
export type { IntegrationDefinition, IntegrationComponentDeclarations, IntegrationProposals, IntegrationCapabilityDeclaration, IntegrationPermissionDeclaration, PartnerWidgetDeclaration, PartnerToolModule, PartnerToolParameters, ToolClassificationProposal, DefinitionCollisionInput, FirstPartyInventory, JsonValue, PartnerWebhookDeclaration, WebhookSignatureDeclaration, WebhookEvent, WebhookResult, PartnerScheduleDeclaration, ScheduleInvocation, ScheduleResult, PartnerOAuthDeclaration, OAuthProviderDeclaration, OAuthTokens, } from './integration-definition.js';
|
package/dist/index.js
CHANGED
|
@@ -25,5 +25,9 @@ export { DNS_NAMESPACE, EKANOS_INTEGRATION_NAMESPACE, derivePlanId, deriveProduc
|
|
|
25
25
|
// Workspace-target contract (F10): one schema, host injects icon validity
|
|
26
26
|
export { WorkspaceTargetSchema, WorkspaceTargetListSchema, WorkspaceTargetSlugSchema, WorkspaceTargetLayoutSchema, createWorkspaceTargetSchema, createWorkspaceTargetListSchema, normalizeWorkspaceTargets, } from './workspace-target.js';
|
|
27
27
|
// The integration-definition contract
|
|
28
|
-
export { IntegrationDefinitionSchema, parseIntegrationDefinition, validateIntegrationDefinitions,
|
|
28
|
+
export { IntegrationDefinitionSchema, parseIntegrationDefinition, validateIntegrationDefinitions,
|
|
29
|
+
// Non-throwing sibling collectors (0.2.0 surface add): recover structured
|
|
30
|
+
// findings instead of a thrown, pre-formatted string. `@ekanos/cli validate`
|
|
31
|
+
// consumes these; the throwing functions above are built on the same rules.
|
|
32
|
+
collectDefinitionFindings, collectCollisionFindings, getDiscoveredToolName, assertPlainDeclaration, deepFreezeDefinition, } from './integration-definition.js';
|
|
29
33
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAsBH,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE7D,6EAA6E;AAC7E,6EAA6E;AAC7E,kCAAkC;AAClC,OAAO,EACL,aAAa,EACb,4BAA4B,EAC5B,YAAY,EACZ,eAAe,EACf,MAAM,GACP,MAAM,cAAc,CAAC;AAEtB,0EAA0E;AAC1E,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,yBAAyB,EACzB,2BAA2B,EAC3B,2BAA2B,EAC3B,+BAA+B,EAC/B,yBAAyB,GAI1B,MAAM,oBAAoB,CAAC;AAE5B,sCAAsC;AACtC,OAAO,EACL,2BAA2B,EAC3B,0BAA0B,EAC1B,8BAA8B,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAsBH,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE7D,6EAA6E;AAC7E,6EAA6E;AAC7E,kCAAkC;AAClC,OAAO,EACL,aAAa,EACb,4BAA4B,EAC5B,YAAY,EACZ,eAAe,EACf,MAAM,GACP,MAAM,cAAc,CAAC;AAEtB,0EAA0E;AAC1E,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,yBAAyB,EACzB,2BAA2B,EAC3B,2BAA2B,EAC3B,+BAA+B,EAC/B,yBAAyB,GAI1B,MAAM,oBAAoB,CAAC;AAE5B,sCAAsC;AACtC,OAAO,EACL,2BAA2B,EAC3B,0BAA0B,EAC1B,8BAA8B;AAC9B,0EAA0E;AAC1E,6EAA6E;AAC7E,4EAA4E;AAC5E,yBAAyB,EACzB,wBAAwB,EACxB,qBAAqB,EACrB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,0BAA0B,CAAC","sourcesContent":["/**\n * @ekanos/integration-schema — the canonical, dependency-pure contract for\n * Ekanos integration definitions.\n *\n * ONE zod schema, ONE set of types, imported by BOTH `@ekanos/sdk`\n * (authoring: `defineIntegration()`) and `@kit/integrations-core` (host trust\n * boundary: `registerPartnerIntegration()` re-parses against this schema).\n * This package depends on nothing but zod, so neither consumer forms a cycle\n * and there is no hand-written structural twin to drift (F3/F9/F10).\n *\n * Depends on: zod. Nothing else — no `@kit/*`, no React, no `server-only`.\n *\n * Relative specifiers are extensionless here on purpose. Workspace consumers\n * resolve this package's raw `src/*.ts` through a bundler, so a `./x.js`\n * specifier would point at a file that does not exist. The published ESM still\n * needs the extension for a real Node import, so `scripts/rewrite-esm-specifiers.mjs`\n * adds it to `dist/` after the compiler runs — see that file for the full\n * rationale. Do not hand-write `.js` extensions back into this source tree.\n */\n\n// Capability-context types (canonical home; @ekanos/sdk re-exports these)\nexport type {\n IntegrationActor,\n IntegrationContext,\n IntegrationStorage,\n ScopedStore,\n IntegrationSecrets,\n IntegrationFetch,\n IntegrationLogger,\n StorageEntry,\n StorageWriteOptions,\n StorageSchemas,\n StorageSchemaMap,\n StorageScopeSchemas,\n StorageKeyDeclaration,\n StorageKeyDeclarationInput,\n StorageKeySchema,\n} from './capability-context';\n\nexport type { ComponentReference } from './component-reference';\nexport { isComponentReference } from './component-reference';\n\n// Deterministic slug → uuid derivation. One slug, one product id, everywhere\n// and forever — the SDK, the seed generator and any future gate all agree by\n// computing rather than choosing.\nexport {\n DNS_NAMESPACE,\n EKANOS_INTEGRATION_NAMESPACE,\n derivePlanId,\n deriveProductId,\n uuidv5,\n} from './product-id';\n\n// Workspace-target contract (F10): one schema, host injects icon validity\nexport {\n WorkspaceTargetSchema,\n WorkspaceTargetListSchema,\n WorkspaceTargetSlugSchema,\n WorkspaceTargetLayoutSchema,\n createWorkspaceTargetSchema,\n createWorkspaceTargetListSchema,\n normalizeWorkspaceTargets,\n type WorkspaceTargetSchemaOptions,\n type WorkspaceTargetDefinition,\n type ResolvedWorkspaceTarget,\n} from './workspace-target';\n\n// The integration-definition contract\nexport {\n IntegrationDefinitionSchema,\n parseIntegrationDefinition,\n validateIntegrationDefinitions,\n // Non-throwing sibling collectors (0.2.0 surface add): recover structured\n // findings instead of a thrown, pre-formatted string. `@ekanos/cli validate`\n // consumes these; the throwing functions above are built on the same rules.\n collectDefinitionFindings,\n collectCollisionFindings,\n getDiscoveredToolName,\n assertPlainDeclaration,\n deepFreezeDefinition,\n} from './integration-definition';\n\nexport type {\n Finding,\n CollectDefinitionOptions,\n} from './integration-definition';\n\nexport type {\n IntegrationDefinition,\n IntegrationComponentDeclarations,\n IntegrationProposals,\n IntegrationCapabilityDeclaration,\n IntegrationPermissionDeclaration,\n PartnerWidgetDeclaration,\n PartnerToolModule,\n PartnerToolParameters,\n ToolClassificationProposal,\n DefinitionCollisionInput,\n FirstPartyInventory,\n JsonValue,\n // Event surfaces (webhooks, schedules, OAuth) — interface-first: the local\n // harness executes them today; the host transports bind to them later.\n PartnerWebhookDeclaration,\n WebhookSignatureDeclaration,\n WebhookEvent,\n WebhookResult,\n PartnerScheduleDeclaration,\n ScheduleInvocation,\n ScheduleResult,\n PartnerOAuthDeclaration,\n OAuthProviderDeclaration,\n OAuthTokens,\n} from './integration-definition';\n"]}
|
|
@@ -1681,6 +1681,38 @@ export interface IntegrationDefinition<Schemas extends StorageSchemas = StorageS
|
|
|
1681
1681
|
oauth?: PartnerOAuthDeclaration<Schemas>;
|
|
1682
1682
|
proposes?: IntegrationProposals;
|
|
1683
1683
|
}
|
|
1684
|
+
/**
|
|
1685
|
+
* One structured validation result. This is the committed shape the CLI and
|
|
1686
|
+
* any other tooling consumes — the collectors below return arrays of these,
|
|
1687
|
+
* and the throwing entry points (`parseIntegrationDefinition`,
|
|
1688
|
+
* `validateIntegrationDefinitions`) are built on the exact same rules so there
|
|
1689
|
+
* is one rule set, not two.
|
|
1690
|
+
*
|
|
1691
|
+
* `line` is deliberately optional and usually ABSENT: zod reports a `path`
|
|
1692
|
+
* (`components.widgets[2].id`), not a byte offset into a source file, and
|
|
1693
|
+
* fabricating a line number would be a lie. The zod path lives in `message`;
|
|
1694
|
+
* `file` names the module the definition was loaded from when the caller knows
|
|
1695
|
+
* it. `hint` is always a non-empty, imperative remediation instruction.
|
|
1696
|
+
*/
|
|
1697
|
+
export interface Finding {
|
|
1698
|
+
check: string;
|
|
1699
|
+
severity: 'error' | 'warn' | 'info';
|
|
1700
|
+
file?: string;
|
|
1701
|
+
line?: number;
|
|
1702
|
+
message: string;
|
|
1703
|
+
hint: string;
|
|
1704
|
+
}
|
|
1705
|
+
export interface CollectDefinitionOptions {
|
|
1706
|
+
/** The module the definition was loaded from, stamped onto every finding. */
|
|
1707
|
+
file?: string;
|
|
1708
|
+
}
|
|
1709
|
+
/**
|
|
1710
|
+
* Non-throwing sibling of `parseIntegrationDefinition`: validates a single
|
|
1711
|
+
* integration definition against the canonical schema and returns structured
|
|
1712
|
+
* findings instead of throwing a pre-formatted string. An empty array means
|
|
1713
|
+
* the definition is valid. Used by `@ekanos/cli validate`.
|
|
1714
|
+
*/
|
|
1715
|
+
export declare function collectDefinitionFindings(input: unknown, options?: CollectDefinitionOptions): Finding[];
|
|
1684
1716
|
/**
|
|
1685
1717
|
* F4: reject accessor/proxy/class-instance/cyclic declaration containers
|
|
1686
1718
|
* before parsing. An object with getters (or a proxy) can return validated
|
|
@@ -1758,14 +1790,11 @@ export interface FirstPartyInventory {
|
|
|
1758
1790
|
toolNames?: readonly string[];
|
|
1759
1791
|
}
|
|
1760
1792
|
/**
|
|
1761
|
-
*
|
|
1762
|
-
*
|
|
1763
|
-
* inventory
|
|
1764
|
-
*
|
|
1765
|
-
* This is the build-time gate the host registry deliberately lacks:
|
|
1766
|
-
* `integrationRegistry.register()` keys by slug via `Map.set` and silently
|
|
1767
|
-
* OVERWRITES, and duplicate widget/tool ids resolve last- or
|
|
1768
|
-
* first-registration-wins by import order.
|
|
1793
|
+
* Non-throwing sibling of `validateIntegrationDefinitions`: returns structured
|
|
1794
|
+
* collision findings across the partner set (and against the first-party
|
|
1795
|
+
* inventory) instead of throwing. An empty array means no collisions. Used by
|
|
1796
|
+
* `@ekanos/cli validate`.
|
|
1769
1797
|
*/
|
|
1798
|
+
export declare function collectCollisionFindings(definitions: readonly DefinitionCollisionInput[], firstParty?: FirstPartyInventory): Finding[];
|
|
1770
1799
|
export declare function validateIntegrationDefinitions(definitions: readonly DefinitionCollisionInput[], firstParty?: FirstPartyInventory): void;
|
|
1771
1800
|
export {};
|
|
@@ -429,14 +429,6 @@ function findDuplicates(values) {
|
|
|
429
429
|
}
|
|
430
430
|
return [...duplicates];
|
|
431
431
|
}
|
|
432
|
-
function formatIssues(issues) {
|
|
433
|
-
return issues
|
|
434
|
-
.map((issue) => {
|
|
435
|
-
const path = issue.path.length > 0 ? issue.path.join('.') : '(root)';
|
|
436
|
-
return ` - ${path}: ${issue.message}`;
|
|
437
|
-
})
|
|
438
|
-
.join('\n');
|
|
439
|
-
}
|
|
440
432
|
const HOST_ASSIGNED_REMINDER = 'Host-assigned fields are never partner-authorable: productId, kind, trust ' +
|
|
441
433
|
'tier, and machine exposure (credentialModel) do not exist on ' +
|
|
442
434
|
'IntegrationDefinition, per-tool effect/sensitivity belong in the ' +
|
|
@@ -444,14 +436,99 @@ const HOST_ASSIGNED_REMINDER = 'Host-assigned fields are never partner-authorabl
|
|
|
444
436
|
'widgetConfigId, workspaceId, collapsed, isPinned, health, ' +
|
|
445
437
|
'integrationMetadata) are populated by the platform at runtime — remove ' +
|
|
446
438
|
'them from the definition.';
|
|
439
|
+
const PLAIN_DATA_HINT = 'Declarations must be finite plain data. Remove the cycle, getter/setter, ' +
|
|
440
|
+
'or class/exotic instance the message names so the value cannot change ' +
|
|
441
|
+
'after validation, then re-run validate.';
|
|
442
|
+
/** Per-issue remediation. Unrecognized keys get the host-assigned reminder. */
|
|
443
|
+
function hintForIssue(issue) {
|
|
444
|
+
if (issue.code === z.ZodIssueCode.unrecognized_keys) {
|
|
445
|
+
return HOST_ASSIGNED_REMINDER;
|
|
446
|
+
}
|
|
447
|
+
const path = issue.path.length > 0 ? issue.path.join('.') : '(root)';
|
|
448
|
+
return (`Correct the value at "${path}" so it satisfies ` +
|
|
449
|
+
`@ekanos/integration-schema's IntegrationDefinitionSchema, then re-run ` +
|
|
450
|
+
`validate.`);
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* The single, shared implementation behind BOTH the non-throwing collector and
|
|
454
|
+
* the throwing `parseIntegrationDefinition`. Runs the plain-data structural
|
|
455
|
+
* check first (short-circuiting exactly as the throwing path always has), then
|
|
456
|
+
* the canonical zod parse. Returns the findings, the sanitized `data` on
|
|
457
|
+
* success, and whether an unrecognized key was among the failures (the
|
|
458
|
+
* throwing path appends the host-assigned reminder only in that case).
|
|
459
|
+
*/
|
|
460
|
+
function collectDefinitionResult(input, options = {}) {
|
|
461
|
+
const { file } = options;
|
|
462
|
+
// Structural pre-check: the same rule assertPlainDeclaration throws on, but
|
|
463
|
+
// captured as a finding. If it fails we stop here, matching the throwing
|
|
464
|
+
// path which never reaches safeParse once the pre-check throws.
|
|
465
|
+
try {
|
|
466
|
+
assertPlainDeclaration(input);
|
|
467
|
+
}
|
|
468
|
+
catch (error) {
|
|
469
|
+
return {
|
|
470
|
+
findings: [
|
|
471
|
+
Object.assign(Object.assign({ check: 'definition.plain-data', severity: 'error' }, (file ? { file } : {})), { message: error instanceof Error ? error.message : String(error), hint: PLAIN_DATA_HINT }),
|
|
472
|
+
],
|
|
473
|
+
hasUnrecognizedKey: false,
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
const result = IntegrationDefinitionSchema.safeParse(input);
|
|
477
|
+
if (result.success) {
|
|
478
|
+
deepFreezeDefinition(result.data);
|
|
479
|
+
return {
|
|
480
|
+
findings: [],
|
|
481
|
+
data: result.data,
|
|
482
|
+
hasUnrecognizedKey: false,
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
const hasUnrecognizedKey = result.error.issues.some((issue) => issue.code === z.ZodIssueCode.unrecognized_keys);
|
|
486
|
+
const findings = result.error.issues.map((issue) => {
|
|
487
|
+
const path = issue.path.length > 0 ? issue.path.join('.') : '(root)';
|
|
488
|
+
return Object.assign(Object.assign({ check: 'definition.schema', severity: 'error' }, (file ? { file } : {})), {
|
|
489
|
+
// The zod path, not a source line — see the Finding doc comment.
|
|
490
|
+
message: `${path}: ${issue.message}`, hint: hintForIssue(issue) });
|
|
491
|
+
});
|
|
492
|
+
return { findings, hasUnrecognizedKey };
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Non-throwing sibling of `parseIntegrationDefinition`: validates a single
|
|
496
|
+
* integration definition against the canonical schema and returns structured
|
|
497
|
+
* findings instead of throwing a pre-formatted string. An empty array means
|
|
498
|
+
* the definition is valid. Used by `@ekanos/cli validate`.
|
|
499
|
+
*/
|
|
500
|
+
export function collectDefinitionFindings(input, options = {}) {
|
|
501
|
+
return collectDefinitionResult(input, options).findings;
|
|
502
|
+
}
|
|
447
503
|
/**
|
|
448
|
-
* A zod schema (storage leaf)
|
|
449
|
-
*
|
|
450
|
-
*
|
|
451
|
-
*
|
|
504
|
+
* A zod schema (storage leaf) or a React exotic (`memo`/`forwardRef`, an
|
|
505
|
+
* object tagged with `$$typeof`). NOTHING here reads a property value:
|
|
506
|
+
* `instanceof` walks the prototype chain and `in` is [[HasProperty]], so a
|
|
507
|
+
* malicious getter still cannot execute during leaf detection (F4).
|
|
508
|
+
*
|
|
509
|
+
* `instanceof z.ZodType` alone is NOT sufficient. It answers "is this an
|
|
510
|
+
* instance of THIS package's zod copy", and a partner's `zod` is routinely a
|
|
511
|
+
* different copy — any transitive dependency pinning a different range, or a
|
|
512
|
+
* package manager that nests instead of deduping, is enough. When the copies
|
|
513
|
+
* differ, `instanceof` is false, `assertPlainDeclaration` walks INTO the
|
|
514
|
+
* schema, and every storage key is rejected as "a class/exotic instance, not
|
|
515
|
+
* a plain object" — an error that says nothing about the real cause and sends
|
|
516
|
+
* the author looking at an object literal that is already correct.
|
|
517
|
+
*
|
|
518
|
+
* So structural detection is the fallback, matching the duck-typing
|
|
519
|
+
* `isZodSchemaLike` already does one layer down for exactly this reason.
|
|
520
|
+
* `~standard` is the Standard Schema marker (zod >= 3.24); `_def` +
|
|
521
|
+
* `safeParse` covers older copies. This widens nothing security-relevant: a
|
|
522
|
+
* value that clears this check still has to satisfy `zodSchemaRef` /
|
|
523
|
+
* `storageKeyDeclarationRef`, which call `.safeParse` regardless, and the
|
|
524
|
+
* re-parse at the host trust boundary remains the real guard.
|
|
452
525
|
*/
|
|
453
526
|
function isDeclarationLeaf(value) {
|
|
454
|
-
|
|
527
|
+
if (value instanceof z.ZodType)
|
|
528
|
+
return true;
|
|
529
|
+
if ('$$typeof' in value)
|
|
530
|
+
return true;
|
|
531
|
+
return '~standard' in value || ('_def' in value && 'safeParse' in value);
|
|
455
532
|
}
|
|
456
533
|
/**
|
|
457
534
|
* F4: reject accessor/proxy/class-instance/cyclic declaration containers
|
|
@@ -480,20 +557,20 @@ export function assertPlainDeclaration(value, path = '(root)', ancestors = new W
|
|
|
480
557
|
return;
|
|
481
558
|
if (ancestors.has(value)) {
|
|
482
559
|
throw new Error(`Integration definition contains a cycle at ${path}. ` +
|
|
483
|
-
`Declarations must be finite plain data — remove the self-reference
|
|
560
|
+
`Declarations must be finite plain data — remove the self-reference.`);
|
|
484
561
|
}
|
|
485
562
|
const proto = Object.getPrototypeOf(value);
|
|
486
563
|
const isArray = Array.isArray(value);
|
|
487
564
|
if (!isArray && proto !== Object.prototype && proto !== null) {
|
|
488
565
|
throw new Error(`Integration definition value at ${path} is a class/exotic instance, not a plain object. ` +
|
|
489
|
-
`Declaration containers must be plain object/array literals so their values cannot mutate after validation
|
|
566
|
+
`Declaration containers must be plain object/array literals so their values cannot mutate after validation.`);
|
|
490
567
|
}
|
|
491
568
|
ancestors.add(value);
|
|
492
569
|
for (const key of Object.keys(value)) {
|
|
493
570
|
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
494
571
|
if (descriptor && (descriptor.get || descriptor.set)) {
|
|
495
572
|
throw new Error(`Integration definition property at ${path}.${key} is a getter/setter, not a data property. ` +
|
|
496
|
-
`Declaration values must be plain data — a getter can return a different value after validation
|
|
573
|
+
`Declaration values must be plain data — a getter can return a different value after validation.`);
|
|
497
574
|
}
|
|
498
575
|
assertPlainDeclaration(value[key], `${path}.${key}`, ancestors);
|
|
499
576
|
}
|
|
@@ -538,26 +615,37 @@ export function deepFreezeDefinition(value) {
|
|
|
538
615
|
* whose message is a remediation instruction.
|
|
539
616
|
*/
|
|
540
617
|
export function parseIntegrationDefinition(input) {
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
//
|
|
553
|
-
//
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
//
|
|
559
|
-
//
|
|
560
|
-
|
|
618
|
+
// Built ON TOP of the collector so there is exactly one rule set. The
|
|
619
|
+
// collector runs assertPlainDeclaration first (short-circuiting), then the
|
|
620
|
+
// canonical parse, and freezes `data` on success (F4) — so a successful
|
|
621
|
+
// result here is already the deep-frozen, sanitized definition.
|
|
622
|
+
const { findings, data, hasUnrecognizedKey } = collectDefinitionResult(input);
|
|
623
|
+
if (data) {
|
|
624
|
+
// The schema's inferred output matches IntegrationDefinition in every
|
|
625
|
+
// non-generic field; the storage/tool generics default to the permissive
|
|
626
|
+
// base, which is exactly right for the loose registration boundary.
|
|
627
|
+
return data;
|
|
628
|
+
}
|
|
629
|
+
// A plain-data structural failure is thrown verbatim (its message is already
|
|
630
|
+
// a remediation: "…contains a cycle…", "…is a getter/setter…").
|
|
631
|
+
const plainDataFinding = findings.find((finding) => finding.check === 'definition.plain-data');
|
|
632
|
+
if (plainDataFinding) {
|
|
633
|
+
throw new Error(plainDataFinding.message);
|
|
634
|
+
}
|
|
635
|
+
// Schema failures reproduce the historical message shape exactly: each
|
|
636
|
+
// finding's message is already `${path}: ${issue.message}`, so re-prefixing
|
|
637
|
+
// with ` - ` reconstructs formatIssues() verbatim.
|
|
638
|
+
const slug = typeof (input === null || input === void 0 ? void 0 : input.slug) === 'string'
|
|
639
|
+
? ` for "${input.slug}"`
|
|
640
|
+
: '';
|
|
641
|
+
// The reminder is six lines about fields the author may not have written.
|
|
642
|
+
// Appending it to EVERY failure buries the one line that matters — a bad
|
|
643
|
+
// semver or a malformed cron arrives under a paragraph about productId and
|
|
644
|
+
// trust tiers. Show it only when an unrecognized key is what failed, which
|
|
645
|
+
// is the case it was written for.
|
|
646
|
+
throw new Error(`Invalid integration definition${slug}:\n` +
|
|
647
|
+
findings.map((finding) => ` - ${finding.message}`).join('\n') +
|
|
648
|
+
(hasUnrecognizedKey ? `\n${HOST_ASSIGNED_REMINDER}` : ''));
|
|
561
649
|
}
|
|
562
650
|
// ---- Cross-definition collision detection (F5) -----------------------------
|
|
563
651
|
/**
|
|
@@ -576,16 +664,11 @@ export function getDiscoveredToolName(slug, rawName) {
|
|
|
576
664
|
return rawName.startsWith(slugPrefix) ? rawName : `${slugPrefix}_${rawName}`;
|
|
577
665
|
}
|
|
578
666
|
/**
|
|
579
|
-
*
|
|
580
|
-
*
|
|
581
|
-
*
|
|
582
|
-
*
|
|
583
|
-
* This is the build-time gate the host registry deliberately lacks:
|
|
584
|
-
* `integrationRegistry.register()` keys by slug via `Map.set` and silently
|
|
585
|
-
* OVERWRITES, and duplicate widget/tool ids resolve last- or
|
|
586
|
-
* first-registration-wins by import order.
|
|
667
|
+
* THE shared collision rule set, returning structured records. Both the
|
|
668
|
+
* throwing `validateIntegrationDefinitions` and the non-throwing
|
|
669
|
+
* `collectCollisionFindings` are built on this, so there is one rule set.
|
|
587
670
|
*/
|
|
588
|
-
|
|
671
|
+
function computeCollisionRecords(definitions, firstParty = {}) {
|
|
589
672
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
590
673
|
const slugCounts = new Map();
|
|
591
674
|
const widgetOwners = new Map();
|
|
@@ -608,20 +691,32 @@ export function validateIntegrationDefinitions(definitions, firstParty = {}) {
|
|
|
608
691
|
]);
|
|
609
692
|
}
|
|
610
693
|
}
|
|
611
|
-
const
|
|
694
|
+
const records = [];
|
|
612
695
|
for (const [slug, count] of slugCounts) {
|
|
613
696
|
if (count > 1) {
|
|
614
|
-
|
|
697
|
+
records.push({
|
|
698
|
+
check: 'collision.slug',
|
|
699
|
+
message: `slug "${slug}" is declared by ${count} partner definitions — slugs are the registry key and must be globally unique.`,
|
|
700
|
+
hint: `Rename all but one of the definitions declaring slug "${slug}" so every slug is globally unique.`,
|
|
701
|
+
});
|
|
615
702
|
}
|
|
616
703
|
}
|
|
617
704
|
for (const [id, owners] of widgetOwners) {
|
|
618
705
|
if (owners.length > 1) {
|
|
619
|
-
|
|
706
|
+
records.push({
|
|
707
|
+
check: 'collision.widget-id',
|
|
708
|
+
message: `widget id "${id}" is declared by [${owners.join(', ')}] — widget ids are global (widget_config rows key on them); prefix yours with the integration slug.`,
|
|
709
|
+
hint: `Prefix widget id "${id}" with your integration slug so it is globally unique.`,
|
|
710
|
+
});
|
|
620
711
|
}
|
|
621
712
|
}
|
|
622
713
|
for (const [name, owners] of toolOwners) {
|
|
623
714
|
if (owners.length > 1) {
|
|
624
|
-
|
|
715
|
+
records.push({
|
|
716
|
+
check: 'collision.tool-name',
|
|
717
|
+
message: `effective tool name "${name}" is declared by [${owners.join(', ')}] — discovery namespaces tool names by slug, so these collapse to one flat key and overwrite each other. Rename so the slug-prefixed names differ.`,
|
|
718
|
+
hint: `Rename the colliding tools so their slug-prefixed effective names differ from "${name}".`,
|
|
719
|
+
});
|
|
625
720
|
}
|
|
626
721
|
}
|
|
627
722
|
const reservedSlugs = new Set((_g = firstParty.slugs) !== null && _g !== void 0 ? _g : []);
|
|
@@ -629,19 +724,49 @@ export function validateIntegrationDefinitions(definitions, firstParty = {}) {
|
|
|
629
724
|
const reservedTools = new Set((_j = firstParty.toolNames) !== null && _j !== void 0 ? _j : []);
|
|
630
725
|
for (const [slug, owners] of groupOwners(definitions, (d) => [d.slug])) {
|
|
631
726
|
if (reservedSlugs.has(slug)) {
|
|
632
|
-
|
|
727
|
+
records.push({
|
|
728
|
+
check: 'collision.reserved-slug',
|
|
729
|
+
message: `slug "${slug}" (declared by [${owners.join(', ')}]) collides with a first-party integration — pick a slug no built-in product uses.`,
|
|
730
|
+
hint: `Choose a different slug than "${slug}" — it is reserved by a first-party integration.`,
|
|
731
|
+
});
|
|
633
732
|
}
|
|
634
733
|
}
|
|
635
734
|
for (const [id, owners] of widgetOwners) {
|
|
636
735
|
if (reservedWidgets.has(id)) {
|
|
637
|
-
|
|
736
|
+
records.push({
|
|
737
|
+
check: 'collision.reserved-widget-id',
|
|
738
|
+
message: `widget id "${id}" (declared by [${owners.join(', ')}]) collides with a first-party widget — the dashboard resolves widgets by id, so this would hijack it. Prefix with the integration slug.`,
|
|
739
|
+
hint: `Prefix widget id "${id}" with your integration slug — it is reserved by a first-party widget.`,
|
|
740
|
+
});
|
|
638
741
|
}
|
|
639
742
|
}
|
|
640
743
|
for (const [name, owners] of toolOwners) {
|
|
641
744
|
if (reservedTools.has(name)) {
|
|
642
|
-
|
|
745
|
+
records.push({
|
|
746
|
+
check: 'collision.reserved-tool-name',
|
|
747
|
+
message: `effective tool name "${name}" (declared by [${owners.join(', ')}]) collides with a first-party tool — the flat, slug-namespaced tool registry would overwrite one with the other. Rename it.`,
|
|
748
|
+
hint: `Rename the tool so its effective name is not "${name}" — that name is reserved by a first-party tool.`,
|
|
749
|
+
});
|
|
643
750
|
}
|
|
644
751
|
}
|
|
752
|
+
return records;
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Non-throwing sibling of `validateIntegrationDefinitions`: returns structured
|
|
756
|
+
* collision findings across the partner set (and against the first-party
|
|
757
|
+
* inventory) instead of throwing. An empty array means no collisions. Used by
|
|
758
|
+
* `@ekanos/cli validate`.
|
|
759
|
+
*/
|
|
760
|
+
export function collectCollisionFindings(definitions, firstParty = {}) {
|
|
761
|
+
return computeCollisionRecords(definitions, firstParty).map((record) => ({
|
|
762
|
+
check: record.check,
|
|
763
|
+
severity: 'error',
|
|
764
|
+
message: record.message,
|
|
765
|
+
hint: record.hint,
|
|
766
|
+
}));
|
|
767
|
+
}
|
|
768
|
+
export function validateIntegrationDefinitions(definitions, firstParty = {}) {
|
|
769
|
+
const collisions = computeCollisionRecords(definitions, firstParty).map((record) => record.message);
|
|
645
770
|
if (collisions.length > 0) {
|
|
646
771
|
throw new Error(`Integration definitions collide (${collisions.length} collision${collisions.length === 1 ? '' : 's'}):\n` +
|
|
647
772
|
collisions.map((line) => ` - ${line}`).join('\n') +
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integration-definition.js","sourceRoot":"","sources":["../src/integration-definition.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The canonical integration-definition contract: ONE zod schema and ONE set\n * of inferred/hand-written types (F9). `@ekanos/sdk`'s `defineIntegration()`\n * validates against this schema at authoring time; `@kit/integrations-core`'s\n * `registerPartnerIntegration()` re-validates against the SAME schema at the\n * host trust boundary (F3). Both packages depend on this one; it depends on\n * neither, so there is no cycle and no hand-written structural twin.\n *\n * Dependency-pure (zod only): partner component refs are checked\n * structurally via `ComponentReference`, so no React dependency leaks in.\n */\nimport { z } from 'zod';\n\nimport type {\n IntegrationContext,\n StorageKeyDeclarationInput,\n StorageSchemas,\n} from './capability-context';\nimport type { ComponentReference } from './component-reference';\nimport { isComponentReference } from './component-reference';\nimport {\n type WorkspaceTargetDefinition,\n WorkspaceTargetListSchema,\n} from './workspace-target';\n\n// ---- JSON-compatible values (F4) ------------------------------------------\n\ntype JsonPrimitive = string | number | boolean | null;\nexport type JsonValue =\n | JsonPrimitive\n | JsonValue[]\n | { [key: string]: JsonValue };\n\nconst jsonValueSchema: z.ZodType<JsonValue> = z.lazy(() =>\n z.union([\n z.string(),\n // `.finite()` rejects Infinity/-Infinity AND NaN (Number.isFinite) — all\n // of which JSON.stringify silently turns to `null`, so they are not\n // JSON-compatible values (F4).\n z.number().finite(),\n z.boolean(),\n z.null(),\n z.array(jsonValueSchema),\n z.record(jsonValueSchema),\n ]),\n);\n\n// ---- Leaf validators -------------------------------------------------------\n\nfunction componentRefSchema(what: string) {\n return z.custom<ComponentReference>(isComponentReference, {\n message: `${what} must be a React component reference (a function component, or a memo/forwardRef/lazy wrapper) — pass the component itself, not an element or a module path.`,\n });\n}\n\nconst zodSchemaRef = z.custom<z.ZodType>(\n (value) =>\n typeof (value as { safeParse?: unknown } | null)?.safeParse === 'function',\n {\n message:\n 'Every storage key must declare a zod schema (e.g. z.object({ … })) — ctx.storage validates reads and writes against it (capability-context ruling 1).',\n },\n);\n\nconst nonEmpty = (what: string) =>\n z.string().min(1, { message: `${what} must be a non-empty string.` });\n\nconst slugSchema = z.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, {\n message:\n 'slug must be kebab-case ([a-z0-9] segments separated by single hyphens), e.g. \"acme-crm\" — it becomes the product slug, route segment, and MCP namespace.',\n});\n\nconst widgetIdSchema = z.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, {\n message:\n 'Widget ids are kebab-case and globally unique, e.g. \"acme-crm-pipeline\" — prefix with the integration slug to stay collision-free.',\n});\n\nconst storageKeySchema = z.string().regex(/^[a-z0-9_-]+(?:\\/[a-z0-9_-]+)?$/, {\n message:\n 'Storage keys are \"<dataType>\" or \"<dataType>/<subtype>\" in lowercase [a-z0-9_-] — they map onto the account/user product-data columns (capability-context ruling 6).',\n});\n\nconst toolNameSchema = z.string().regex(/^[a-z][a-z0-9_]*$/, {\n message:\n 'Tool names are lowercase snake_case starting with a letter, e.g. \"list_invoices\" — the model calls them by this exact string.',\n});\n\nconst webhookIdSchema = z.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, {\n message:\n 'Webhook ids are kebab-case, e.g. \"payment-updated\" — the host ingress route addresses the handler by this exact string.',\n});\n\nconst scheduleIdSchema = z.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, {\n message:\n 'Schedule ids are kebab-case, e.g. \"daily-reconcile\" — the host scheduler addresses the handler by this exact string.',\n});\n\n// Origin-only egress entries (ruling 3): absolute https origins, optional\n// `*.` subdomain wildcard, no path/query/hash/credentials/http. Kept as a\n// pure regex here so this package depends on nothing; the SDK's shared\n// `parseEgressEntry`/`isEgressAllowed` matcher enforces the identical shape\n// at runtime.\nconst egressEntrySchema = z.string().superRefine((entry, ctx) => {\n const match = /^https:\\/\\/(\\*\\.)?([a-z0-9.-]+)(?::(\\d+))?$/i.exec(entry);\n if (!match) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message:\n `Egress entry \"${entry}\" is invalid. Entries are https origins only — ` +\n `\"https://api.example.com\" (exact) or \"https://*.example.com\" ` +\n `(subdomain wildcard): scheme + host + optional port, no path, query, ` +\n `hash, credentials, or http. Fix it in the integration's egress list.`,\n });\n return;\n }\n const host = match[2] ?? '';\n if (host.includes('*') || host.startsWith('.') || host.endsWith('.')) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Egress entry \"${entry}\" has a malformed host — wildcards are only supported as a single leading \"*.\" (e.g. \"https://*.example.com\").`,\n });\n }\n});\n\n// ---- Sub-object schemas ----------------------------------------------------\n\nconst capabilitySchema = z\n .object({\n label: nonEmpty('capabilities[].label'),\n description: nonEmpty('capabilities[].description'),\n icon: componentRefSchema('capabilities[].icon').optional(),\n })\n .strict();\n\nconst permissionSchema = z\n .object({\n label: nonEmpty('permissions[].label'),\n detail: nonEmpty('permissions[].detail'),\n type: z.enum(['read', 'write']),\n })\n .strict();\n\nconst gridUnitSchema = z\n .object({\n cols: z.number().int().positive(),\n rows: z.number().int().positive(),\n })\n .strict();\n\nconst layoutBoxSchema = z\n .object({\n x: z.number(),\n y: z.number(),\n w: z.number(),\n h: z.number(),\n maxHeight: z.number().optional(),\n })\n .strict();\n\n/**\n * F7: authorable widget fields ONLY. Host-resolved fields (`productId`,\n * `widgetConfigId`, `workspaceId`, `collapsed`, `isPinned`, `health`,\n * `integrationMetadata`) are absent by design and rejected at runtime by\n * `.strict()` — the type and the runtime agree. The host adapter maps this\n * into the full `WidgetConfig`.\n */\nconst widgetSchema = z\n .object({\n id: widgetIdSchema,\n name: nonEmpty('widgets[].name'),\n component: componentRefSchema('widgets[].component'),\n widgetState: z.enum(['active', 'inactive', 'disabled']),\n gridSize: z.union([gridUnitSchema, z.array(gridUnitSchema)]).optional(),\n gridPosition: z\n .object({ col: z.number(), row: z.number() })\n .strict()\n .optional(),\n layouts: z\n .object({\n lg: layoutBoxSchema.optional(),\n md: layoutBoxSchema.optional(),\n sm: layoutBoxSchema.optional(),\n })\n .strict()\n .optional(),\n category: z\n .object({\n id: z.string(),\n name: z.string(),\n slug: z.string(),\n icon: z.string().nullable(),\n })\n .strict()\n .optional(),\n isCollapsible: z.boolean().optional(),\n isPinnable: z.boolean().optional(),\n aiFooterEnabled: z.boolean().optional(),\n })\n .strict();\n\nconst toolParametersSchema = z\n .object({\n type: z.literal('object'),\n properties: z.record(jsonValueSchema).optional(),\n required: z.array(z.string()).optional(),\n additionalProperties: z.boolean().optional(),\n })\n .strict();\n\nconst toolRunSchema = z.custom<\n (ctx: never, args: Record<string, unknown>) => Promise<unknown>\n>((value) => typeof value === 'function', {\n message:\n 'tools[].run must be a function (ctx, args) => Promise<result> — it receives the host-scoped IntegrationContext, never a raw client.',\n});\n\nconst toolSchema = z\n .object({\n name: toolNameSchema,\n description: nonEmpty('tools[].description'),\n parameters: toolParametersSchema.optional(),\n run: toolRunSchema,\n outputExample: z.record(jsonValueSchema).optional(),\n })\n .strict();\n\n// ---- Event surfaces (webhooks, schedules, OAuth) ---------------------------\n//\n// Declared exactly like MCP tools: metadata parsed strictly, handlers checked\n// structurally as functions (`z.custom`) and carried through the parse\n// untouched. The declarations are the CONTRACT; every transport — the local\n// harness today, the host's public ingress/scheduler/hosted-callback later —\n// binds to these same fields, so a partner package never changes when the\n// real transports arrive.\n\nfunction handlerSchema(what: string, shape: string) {\n return z.custom<(ctx: never, arg: never) => Promise<unknown>>(\n (value) => typeof value === 'function',\n {\n message: `${what} must be a function ${shape} — it receives the host-scoped IntegrationContext, never a raw request or client.`,\n },\n );\n}\n\nconst payloadSchemaRef = z.custom<z.ZodType>(\n (value) =>\n typeof (value as { safeParse?: unknown } | null)?.safeParse === 'function',\n {\n message:\n 'webhooks[].payloadSchema must be a zod schema (e.g. z.object({ … })) — the transport validates every delivery against it before the handler runs.',\n },\n);\n\n/**\n * How the TRANSPORT verifies a delivery. Verification is never the partner's\n * job: the declaration names the signature header and the secret that signs\n * it; the host ingress enforces it (the local harness logs it as skipped).\n * `'none'` is an explicit statement that the source is unsigned.\n */\nconst webhookSignatureSchema = z.union([\n z.literal('none'),\n z\n .object({\n header: nonEmpty('webhooks[].signature.header'),\n secretName: nonEmpty('webhooks[].signature.secretName'),\n })\n .strict(),\n]);\n\nconst webhookSchema = z\n .object({\n id: webhookIdSchema,\n description: nonEmpty('webhooks[].description'),\n payloadSchema: payloadSchemaRef,\n signature: webhookSignatureSchema,\n examplePayload: z.record(jsonValueSchema).optional(),\n handler: handlerSchema(\n 'webhooks[].handler',\n '(ctx, event) => Promise<WebhookResult>',\n ),\n })\n .strict();\n\nconst scheduleSchema = z\n .object({\n id: scheduleIdSchema,\n description: nonEmpty('schedules[].description'),\n // Presence only here — the dependency-pure schema package stays zod-only,\n // so the real 5-field cron syntax check lives in the SDK layer\n // (`defineIntegration()`), the same way it layers cross-field rules today.\n cron: nonEmpty('schedules[].cron'),\n handler: handlerSchema(\n 'schedules[].handler',\n '(ctx, invocation) => Promise<ScheduleResult>',\n ),\n })\n .strict();\n\nconst httpsUrlSchema = (what: string) =>\n z.string().superRefine((value, ctx) => {\n let parsed: URL;\n try {\n parsed = new URL(value);\n } catch {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `${what} must be an absolute URL, e.g. \"https://provider.example/oauth/authorize\".`,\n });\n return;\n }\n if (parsed.protocol !== 'https:') {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `${what} must use https — OAuth endpoints are never plain http.`,\n });\n }\n if (parsed.username !== '' || parsed.password !== '') {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `${what} must not embed credentials.`,\n });\n }\n });\n\nconst oauthSchema = z\n .object({\n provider: z\n .object({\n authorizationUrl: httpsUrlSchema('oauth.provider.authorizationUrl'),\n tokenUrl: httpsUrlSchema('oauth.provider.tokenUrl'),\n scopes: z.array(nonEmpty('oauth.provider.scopes[]')),\n pkce: z.boolean().optional(),\n })\n .strict(),\n credentials: z\n .object({\n clientIdSecretName: nonEmpty('oauth.credentials.clientIdSecretName'),\n clientSecretSecretName: nonEmpty(\n 'oauth.credentials.clientSecretSecretName',\n ),\n })\n .strict(),\n onTokens: handlerSchema('oauth.onTokens', '(ctx, tokens) => Promise<void>'),\n })\n .strict();\n\nconst toolClassificationProposalSchema = z\n .object({\n effect: z.enum(['read', 'write']).optional(),\n sensitivity: z.enum(['public', 'internal', 'pii', 'financial']).optional(),\n })\n .strict();\n\nconst proposalsSchema = z\n .object({\n credentialModel: z.enum(['account', 'user', 'source']).optional(),\n tools: z.record(toolClassificationProposalSchema).optional(),\n })\n .strict();\n\n/**\n * A storage key's EXPLICIT declaration: the zod schema plus its exposure\n * flags. `clientReadable` is the only way a declared key becomes readable by\n * the browser through the generic storage route — and it defaults to false,\n * so the bare-schema form stays server-only exactly as it always was.\n * `.strict()` keeps an unrecognized flag (a typo like `clientReadible`) an\n * error rather than a silently-ignored key whose author believes it is\n * exposed — or, worse, believes it is not.\n */\nconst storageKeyDeclarationSchema = z\n .object({\n schema: zodSchemaRef,\n clientReadable: z.boolean().optional(),\n })\n .strict();\n\n/** Duck-typed so a partner's own bundled zod copy still reads as a schema. */\nfunction isZodSchemaLike(value: unknown): boolean {\n return (\n typeof (value as { safeParse?: unknown } | null)?.safeParse === 'function'\n );\n}\n\n/**\n * Either declaration form, hand-routed rather than expressed as `z.union` so\n * the failure message stays specific. A union reports a bare \"Invalid input\"\n * for every wrong shape, which would lose both the \"declare a zod schema\"\n * guidance AND the strict-descriptor typo report — the two errors an author\n * is actually going to hit.\n */\nconst storageKeyDeclarationRef = z\n .custom<StorageKeyDeclarationInput>(() => true)\n .superRefine((value, ctx) => {\n if (isZodSchemaLike(value)) return;\n\n const looksLikeDescriptor =\n value !== null && typeof value === 'object' && !Array.isArray(value);\n\n // Neither form: name both, since the descriptor is the less obvious one.\n if (\n !looksLikeDescriptor ||\n !isZodSchemaLike((value as { schema?: unknown }).schema)\n ) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message:\n 'Every storage key must declare either a zod schema (e.g. z.object({ … })) or a { schema, clientReadable } descriptor — ctx.storage validates reads and writes against the schema (capability-context ruling 1), and clientReadable (default false) is what opts the key in to the browser-readable storage route.',\n });\n return;\n }\n\n // A real descriptor with a real schema — report its own issues verbatim\n // (an unrecognized flag, a non-boolean clientReadable) rather than the\n // generic message, which would send the author looking in the wrong place.\n const result = storageKeyDeclarationSchema.safeParse(value);\n if (result.success) return;\n\n for (const issue of result.error.issues) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: issue.path,\n message: issue.message,\n });\n }\n });\n\nconst storageScopeSchema = z.record(storageKeySchema, storageKeyDeclarationRef);\n\nconst componentsSchema = z\n .object({\n activationForm: componentRefSchema('components.activationForm').optional(),\n marketplaceTile: componentRefSchema(\n 'components.marketplaceTile',\n ).optional(),\n widgets: z.array(widgetSchema).optional(),\n })\n .strict();\n\n/**\n * THE canonical schema. Strict everywhere: an unrecognized key is an error,\n * which is what keeps host-assigned fields (productId, kind, trust tier,\n * credentialModel, per-tool effect/sensitivity, host-resolved widget fields)\n * structurally un-settable at runtime, not merely absent from the type.\n */\nexport const IntegrationDefinitionSchema = z\n .object({\n slug: slugSchema,\n name: nonEmpty('name'),\n description: nonEmpty('description'),\n version: z\n .string()\n .regex(\n /^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$/,\n {\n message:\n 'version must be semver (\"1.0.0\", optionally with a prerelease/build suffix) — promotion diffs definitions by it.',\n },\n ),\n capabilities: z.array(capabilitySchema).optional(),\n permissions: z.array(permissionSchema).optional(),\n components: componentsSchema.optional(),\n workspaceTargets: WorkspaceTargetListSchema.optional(),\n tools: z.array(toolSchema).optional(),\n storage: z\n .object({\n account: storageScopeSchema.optional(),\n user: storageScopeSchema.optional(),\n })\n .strict()\n .optional(),\n egress: z.array(egressEntrySchema).optional(),\n webhooks: z.array(webhookSchema).optional(),\n schedules: z.array(scheduleSchema).optional(),\n oauth: oauthSchema.optional(),\n proposes: proposalsSchema.optional(),\n })\n .strict()\n .superRefine((definition, ctx) => {\n const webhookIds = (definition.webhooks ?? []).map((w) => w.id);\n for (const id of findDuplicates(webhookIds)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['webhooks'],\n message: `Webhook id \"${id}\" is declared more than once — give every webhook a unique id.`,\n });\n }\n\n const scheduleIds = (definition.schedules ?? []).map((s) => s.id);\n for (const id of findDuplicates(scheduleIds)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['schedules'],\n message: `Schedule id \"${id}\" is declared more than once — give every schedule a unique id.`,\n });\n }\n\n const widgetIds = (definition.components?.widgets ?? []).map((w) => w.id);\n for (const id of findDuplicates(widgetIds)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['components', 'widgets'],\n message: `Widget id \"${id}\" is declared more than once — give every widget a unique id.`,\n });\n }\n\n const toolNames = (definition.tools ?? []).map((tool) => tool.name);\n for (const name of findDuplicates(toolNames)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['tools'],\n message: `Tool \"${name}\" is declared more than once — give every tool a unique name.`,\n });\n }\n\n const declaredTools = new Set(toolNames);\n for (const proposedName of Object.keys(definition.proposes?.tools ?? {})) {\n if (!declaredTools.has(proposedName)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['proposes', 'tools', proposedName],\n message: `proposes.tools[\"${proposedName}\"] does not match any declared tool — proposals are keyed by the exact tool name in \\`tools\\`.`,\n });\n }\n }\n });\n\n// ---- Hand-written generic types (the parts a non-generic schema cannot\n// express) plus inferred types for everything else. One home, imported by\n// both @ekanos/sdk and @kit/integrations-core. -------------------------------\n\nexport type ToolClassificationProposal = z.infer<\n typeof toolClassificationProposalSchema\n>;\nexport type IntegrationProposals = z.infer<typeof proposalsSchema>;\nexport type PartnerToolParameters = z.infer<typeof toolParametersSchema>;\nexport type IntegrationCapabilityDeclaration = z.infer<typeof capabilitySchema>;\nexport type IntegrationPermissionDeclaration = z.infer<typeof permissionSchema>;\nexport type PartnerWidgetDeclaration = z.infer<typeof widgetSchema>;\n\nexport interface PartnerToolModule<\n Schemas extends StorageSchemas = StorageSchemas,\n> {\n name: string;\n description: string;\n parameters?: PartnerToolParameters;\n /**\n * Contravariant function property (F8): the declared `Schemas` generic\n * types `ctx.storage` for the author. The generic cannot survive the\n * by-value, monomorphic host registration boundary — the adapter erases it\n * — but nothing rests on it surviving: the host constructs `ctx` FROM the\n * definition's own `storage` schemas, and `ctx.storage` validates every\n * read/write against them at runtime regardless of the handler's\n * annotation. The static generic is DX; the runtime schema is the guard.\n */\n run: (\n ctx: IntegrationContext<Schemas>,\n args: Record<string, unknown>,\n ) => Promise<unknown>;\n outputExample?: Record<string, JsonValue>;\n}\n\nexport interface IntegrationComponentDeclarations {\n activationForm?: ComponentReference;\n marketplaceTile?: ComponentReference;\n widgets?: PartnerWidgetDeclaration[];\n}\n\n// ---- Event-surface types (webhooks, schedules, OAuth) ----------------------\n//\n// Hand-written generics like `PartnerToolModule`: the `Schemas` generic types\n// `ctx.storage` for the author and is erased at the host boundary, where the\n// runtime storage validator — built from the definition's own `storage`\n// schemas — is the guard.\n\n/**\n * How the transport verifies a webhook delivery. `'none'` states explicitly\n * that the source is unsigned; otherwise the transport reads the named header\n * and verifies it against the named secret. Verification is the TRANSPORT's\n * job (the local harness logs it as skipped; the host ingress enforces it) —\n * never the partner handler's.\n */\nexport type WebhookSignatureDeclaration =\n | 'none'\n | { header: string; secretName: string };\n\n/**\n * One delivery, as the handler receives it: transport-assigned id and receipt\n * time, the delivery headers, and the payload ALREADY parsed and validated\n * against the declaration's `payloadSchema`. A payload that fails the schema\n * never reaches the handler.\n */\nexport interface WebhookEvent {\n id: string;\n /** ISO-8601 — when the transport accepted the delivery. */\n receivedAt: string;\n headers: Record<string, string>;\n /** The parsed, schema-validated payload (output of `payloadSchema`). */\n payload: unknown;\n}\n\n/**\n * What the handler tells the transport. `processed` acknowledges the event;\n * `ignored` acknowledges it as irrelevant (still a 2xx — the sender must not\n * retry). A handler that cannot process a valid event THROWS, which the\n * transport maps to a retryable failure.\n */\nexport interface WebhookResult {\n status: 'processed' | 'ignored';\n detail?: string;\n}\n\nexport interface PartnerWebhookDeclaration<\n Schemas extends StorageSchemas = StorageSchemas,\n> {\n id: string;\n description: string;\n /** Validates every delivery before the handler runs. */\n payloadSchema: z.ZodType;\n signature: WebhookSignatureDeclaration;\n /**\n * A representative payload, JSON-compatible. Seeds the harness's payload\n * editor and documents the shape beside the schema.\n */\n examplePayload?: Record<string, JsonValue>;\n handler: (\n ctx: IntegrationContext<Schemas>,\n event: WebhookEvent,\n ) => Promise<WebhookResult>;\n}\n\n/**\n * One firing, as the handler receives it. `trigger` distinguishes the real\n * scheduler from a human pressing \"Run now\" (harness or admin) — handlers may\n * branch on it (e.g. skip idempotency windows for manual runs) but must be\n * safe under both.\n */\nexport interface ScheduleInvocation {\n /** ISO-8601 — the tick this invocation stands for. */\n scheduledFor: string;\n /** ISO-8601 — when the handler actually started. */\n invokedAt: string;\n trigger: 'schedule' | 'manual';\n}\n\n/**\n * `completed` means the run did its work; `skipped` means it correctly did\n * nothing (not configured, nothing to do). A handler that fails THROWS, which\n * the transport records as a failed run.\n */\nexport interface ScheduleResult {\n status: 'completed' | 'skipped';\n detail?: string;\n}\n\nexport interface PartnerScheduleDeclaration<\n Schemas extends StorageSchemas = StorageSchemas,\n> {\n id: string;\n description: string;\n /**\n * Standard 5-field cron (minute hour day-of-month month day-of-week),\n * validated by `defineIntegration()`. The schema package checks presence\n * only — full syntax validation is the SDK layer's job.\n */\n cron: string;\n handler: (\n ctx: IntegrationContext<Schemas>,\n invocation: ScheduleInvocation,\n ) => Promise<ScheduleResult>;\n}\n\n/**\n * The token set the transport hands `onTokens` after a code exchange (and\n * after each refresh). `raw` carries provider-specific extras verbatim.\n */\nexport interface OAuthTokens {\n accessToken: string;\n refreshToken?: string;\n /** ISO-8601 expiry, when the provider reports one. */\n expiresAt?: string;\n scope?: string;\n tokenType?: string;\n raw?: Record<string, JsonValue>;\n}\n\nexport interface OAuthProviderDeclaration {\n authorizationUrl: string;\n tokenUrl: string;\n scopes: string[];\n pkce?: boolean;\n}\n\n/**\n * The OAuth contract. The TRANSPORT owns the flow (authorize redirect, state,\n * callback, code exchange — localhost in the harness, hosted later); the\n * partner declares the provider endpoints, names the client-credential\n * secrets, and persists tokens in `onTokens` via `ctx.secrets` — so token\n * storage policy is the existing capability layer, nothing new.\n * `defineIntegration()` rejects the declaration unless both endpoint origins\n * are covered by the definition's `egress` list.\n */\nexport interface PartnerOAuthDeclaration<\n Schemas extends StorageSchemas = StorageSchemas,\n> {\n provider: OAuthProviderDeclaration;\n credentials: {\n clientIdSecretName: string;\n clientSecretSecretName: string;\n };\n onTokens: (\n ctx: IntegrationContext<Schemas>,\n tokens: OAuthTokens,\n ) => Promise<void>;\n}\n\nexport interface IntegrationDefinition<\n Schemas extends StorageSchemas = StorageSchemas,\n> {\n slug: string;\n name: string;\n description: string;\n version: string;\n capabilities?: IntegrationCapabilityDeclaration[];\n permissions?: IntegrationPermissionDeclaration[];\n components?: IntegrationComponentDeclarations;\n workspaceTargets?: WorkspaceTargetDefinition[];\n tools?: PartnerToolModule<Schemas>[];\n storage?: Schemas;\n egress?: string[];\n webhooks?: PartnerWebhookDeclaration<Schemas>[];\n schedules?: PartnerScheduleDeclaration<Schemas>[];\n oauth?: PartnerOAuthDeclaration<Schemas>;\n proposes?: IntegrationProposals;\n}\n\n// ---- Shared helpers --------------------------------------------------------\n\nfunction findDuplicates(values: readonly string[]): string[] {\n const seen = new Set<string>();\n const duplicates = new Set<string>();\n for (const value of values) {\n if (seen.has(value)) duplicates.add(value);\n seen.add(value);\n }\n return [...duplicates];\n}\n\nfunction formatIssues(issues: readonly z.ZodIssue[]): string {\n return issues\n .map((issue) => {\n const path = issue.path.length > 0 ? issue.path.join('.') : '(root)';\n return ` - ${path}: ${issue.message}`;\n })\n .join('\\n');\n}\n\nconst HOST_ASSIGNED_REMINDER =\n 'Host-assigned fields are never partner-authorable: productId, kind, trust ' +\n 'tier, and machine exposure (credentialModel) do not exist on ' +\n 'IntegrationDefinition, per-tool effect/sensitivity belong in the ' +\n '`proposes` block, and host-resolved widget fields (productId, ' +\n 'widgetConfigId, workspaceId, collapsed, isPinned, health, ' +\n 'integrationMetadata) are populated by the platform at runtime — remove ' +\n 'them from the definition.';\n\n/**\n * A zod schema (storage leaf) — detected via `instanceof` so we NEVER read a\n * property (like `.safeParse`) that could be a malicious getter (F4). A React\n * exotic (`memo`/`forwardRef`) is an object tagged with `$$typeof`; the `in`\n * check uses [[HasProperty]], which does not invoke a getter either.\n */\nfunction isDeclarationLeaf(value: object): boolean {\n return value instanceof z.ZodType || '$$typeof' in value;\n}\n\n/**\n * F4: reject accessor/proxy/class-instance/cyclic declaration containers\n * before parsing. An object with getters (or a proxy) can return validated\n * values during parse and different values later; a non-plain prototype can\n * smuggle mutable state past `z.object()`; a cycle would recurse into zod\n * rather than fail cleanly. We walk every CONTAINER (plain object / array),\n * and stop at legitimate leaves: functions (component refs, `run`) and zod\n * schemas (storage). Leaf detection happens BEFORE any own-property read, so\n * a `safeParse` getter cannot execute. Proxy detection is best-effort — the\n * re-parse at the host boundary (which materializes fresh values via zod) is\n * the real guard.\n *\n * Cycle detection tracks the ANCESTOR chain only (add on enter, remove on\n * exit): a genuine back-edge is a cycle, but the same object referenced from\n * two sibling branches (a DAG — e.g. a shallow-cloned widget sharing a\n * `layouts` object) is not, and must not be rejected.\n */\nexport function assertPlainDeclaration(\n value: unknown,\n path = '(root)',\n ancestors: WeakSet<object> = new WeakSet(),\n): void {\n if (value === null || typeof value !== 'object') return;\n\n if (typeof value === 'function') return;\n\n // Leaf detection first — instanceof / HasProperty never invoke a getter.\n if (isDeclarationLeaf(value)) return;\n\n if (ancestors.has(value)) {\n throw new Error(\n `Integration definition contains a cycle at ${path}. ` +\n `Declarations must be finite plain data — remove the self-reference. ${HOST_ASSIGNED_REMINDER}`,\n );\n }\n\n const proto = Object.getPrototypeOf(value) as unknown;\n const isArray = Array.isArray(value);\n if (!isArray && proto !== Object.prototype && proto !== null) {\n throw new Error(\n `Integration definition value at ${path} is a class/exotic instance, not a plain object. ` +\n `Declaration containers must be plain object/array literals so their values cannot mutate after validation. ${HOST_ASSIGNED_REMINDER}`,\n );\n }\n\n ancestors.add(value);\n for (const key of Object.keys(value)) {\n const descriptor = Object.getOwnPropertyDescriptor(value, key);\n if (descriptor && (descriptor.get || descriptor.set)) {\n throw new Error(\n `Integration definition property at ${path}.${key} is a getter/setter, not a data property. ` +\n `Declaration values must be plain data — a getter can return a different value after validation. ${HOST_ASSIGNED_REMINDER}`,\n );\n }\n assertPlainDeclaration(\n (value as Record<string, unknown>)[key],\n `${path}.${key}`,\n ancestors,\n );\n }\n ancestors.delete(value);\n}\n\nconst frozen = new WeakSet<object>();\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object') return false;\n const proto = Object.getPrototypeOf(value) as unknown;\n return proto === Object.prototype || proto === null;\n}\n\n/**\n * Cycle-aware deep freeze (F4). Freezes plain objects and arrays; leaves zod\n * schemas (freezing breaks their internal caches) and functions alone.\n */\nexport function deepFreezeDefinition(value: unknown): void {\n if (value === null || typeof value !== 'object') return;\n if (frozen.has(value)) return;\n\n if (Array.isArray(value)) {\n frozen.add(value);\n Object.freeze(value);\n for (const item of value) deepFreezeDefinition(item);\n return;\n }\n if (isPlainObject(value)) {\n frozen.add(value);\n Object.freeze(value);\n for (const item of Object.values(value)) deepFreezeDefinition(item);\n }\n}\n\n/**\n * The single validation entry point used by BOTH `defineIntegration()` (SDK,\n * authoring time) and `registerPartnerIntegration()` (core, host trust\n * boundary — F3). Rejects non-plain containers, then parses against the\n * canonical schema, and returns the SANITIZED `result.data` (fresh, plain,\n * strict-stripped — never the caller's original object). Throws an Error\n * whose message is a remediation instruction.\n */\nexport function parseIntegrationDefinition(\n input: unknown,\n): IntegrationDefinition {\n assertPlainDeclaration(input);\n\n const result = IntegrationDefinitionSchema.safeParse(input);\n if (!result.success) {\n const slug =\n typeof (input as { slug?: unknown } | null)?.slug === 'string'\n ? ` for \"${(input as { slug: string }).slug}\"`\n : '';\n throw new Error(\n `Invalid integration definition${slug}:\\n` +\n `${formatIssues(result.error.issues)}\\n` +\n HOST_ASSIGNED_REMINDER,\n );\n }\n\n // F4: freeze inside the canonical parser so BOTH defineIntegration() and\n // registerPartnerIntegration() register immutable output — the host boundary\n // no longer hands back mutable arrays. Function/zod leaves stay executable\n // by design (the T1 model), so this is structural immutability, not\n // behavioral.\n deepFreezeDefinition(result.data);\n\n // The schema's inferred output matches IntegrationDefinition in every\n // non-generic field; the storage/tool generics default to the permissive\n // base, which is exactly right for the loose registration boundary.\n return result.data as unknown as IntegrationDefinition;\n}\n\n// ---- Cross-definition collision detection (F5) -----------------------------\n\n/**\n * THE canonical effective MCP tool name — the single source of truth for how\n * discovery keys a tool. Tool discovery namespaces each raw tool name with the\n * integration slug (`slug.replace(/-/g,'_')`), skipping the prefix when the\n * name already carries it. Two collision-free RAW pairs can therefore collapse\n * to the same EFFECTIVE name (`{slug:\"foo\",tool:\"bar_baz\"}` and\n * `{slug:\"foo-bar\",tool:\"baz\"}` both become `foo_bar_baz`), so collision\n * checking MUST compare effective names, and runtime discovery MUST throw on a\n * duplicate assignment. Both call this one helper\n * (`packages/agents/src/tools/tool-discovery.ts`).\n */\nexport function getDiscoveredToolName(slug: string, rawName: string): string {\n const slugPrefix = slug.replace(/-/g, '_');\n return rawName.startsWith(slugPrefix) ? rawName : `${slugPrefix}_${rawName}`;\n}\n\n/**\n * The metadata-only shape collision checking needs — no handlers, no schemas\n * (F8: collision validation must not force widening the tool handlers). A\n * full `IntegrationDefinition` is assignable to it.\n */\nexport interface DefinitionCollisionInput {\n slug: string;\n components?: { widgets?: readonly { id: string }[] } | null;\n tools?: readonly { name: string }[] | null;\n}\n\n/**\n * First-party identifiers a partner definition must not collide with (F5).\n * Widget lookup matches on `widget.id` and the assistant's tool list is a\n * flat name-keyed map where a later registration overwrites an earlier one,\n * so a partner reusing a first-party id/name silently hijacks it. Sourced\n * from the reviewed registry inventory, not from executing partner handlers.\n */\nexport interface FirstPartyInventory {\n slugs?: readonly string[];\n widgetIds?: readonly string[];\n /**\n * EFFECTIVE (discovery) tool names — `getDiscoveredToolName(slug, rawName)` —\n * NOT raw names, since discovery keys the flat registry by the effective name.\n */\n toolNames?: readonly string[];\n}\n\n/**\n * Detects cross-definition collisions (duplicate slugs, widget ids, tool\n * names across the partner set) AND collisions against the first-party\n * inventory, throwing one error listing EVERY collision.\n *\n * This is the build-time gate the host registry deliberately lacks:\n * `integrationRegistry.register()` keys by slug via `Map.set` and silently\n * OVERWRITES, and duplicate widget/tool ids resolve last- or\n * first-registration-wins by import order.\n */\nexport function validateIntegrationDefinitions(\n definitions: readonly DefinitionCollisionInput[],\n firstParty: FirstPartyInventory = {},\n): void {\n const slugCounts = new Map<string, number>();\n const widgetOwners = new Map<string, string[]>();\n const toolOwners = new Map<string, string[]>();\n\n for (const definition of definitions) {\n slugCounts.set(definition.slug, (slugCounts.get(definition.slug) ?? 0) + 1);\n for (const widget of definition.components?.widgets ?? []) {\n widgetOwners.set(widget.id, [\n ...(widgetOwners.get(widget.id) ?? []),\n definition.slug,\n ]);\n }\n for (const tool of definition.tools ?? []) {\n // EFFECTIVE (discovery) name, not the raw name — two collision-free raw\n // names can collapse to the same effective key.\n const effective = getDiscoveredToolName(definition.slug, tool.name);\n toolOwners.set(effective, [\n ...(toolOwners.get(effective) ?? []),\n definition.slug,\n ]);\n }\n }\n\n const collisions: string[] = [];\n\n for (const [slug, count] of slugCounts) {\n if (count > 1) {\n collisions.push(\n `slug \"${slug}\" is declared by ${count} partner definitions — slugs are the registry key and must be globally unique.`,\n );\n }\n }\n for (const [id, owners] of widgetOwners) {\n if (owners.length > 1) {\n collisions.push(\n `widget id \"${id}\" is declared by [${owners.join(', ')}] — widget ids are global (widget_config rows key on them); prefix yours with the integration slug.`,\n );\n }\n }\n for (const [name, owners] of toolOwners) {\n if (owners.length > 1) {\n collisions.push(\n `effective tool name \"${name}\" is declared by [${owners.join(', ')}] — discovery namespaces tool names by slug, so these collapse to one flat key and overwrite each other. Rename so the slug-prefixed names differ.`,\n );\n }\n }\n\n const reservedSlugs = new Set(firstParty.slugs ?? []);\n const reservedWidgets = new Set(firstParty.widgetIds ?? []);\n const reservedTools = new Set(firstParty.toolNames ?? []);\n\n for (const [slug, owners] of groupOwners(definitions, (d) => [d.slug])) {\n if (reservedSlugs.has(slug)) {\n collisions.push(\n `slug \"${slug}\" (declared by [${owners.join(', ')}]) collides with a first-party integration — pick a slug no built-in product uses.`,\n );\n }\n }\n for (const [id, owners] of widgetOwners) {\n if (reservedWidgets.has(id)) {\n collisions.push(\n `widget id \"${id}\" (declared by [${owners.join(', ')}]) collides with a first-party widget — the dashboard resolves widgets by id, so this would hijack it. Prefix with the integration slug.`,\n );\n }\n }\n for (const [name, owners] of toolOwners) {\n if (reservedTools.has(name)) {\n collisions.push(\n `effective tool name \"${name}\" (declared by [${owners.join(', ')}]) collides with a first-party tool — the flat, slug-namespaced tool registry would overwrite one with the other. Rename it.`,\n );\n }\n }\n\n if (collisions.length > 0) {\n throw new Error(\n `Integration definitions collide (${collisions.length} collision${collisions.length === 1 ? '' : 's'}):\\n` +\n collisions.map((line) => ` - ${line}`).join('\\n') +\n '\\nRename until every slug, widget id, and tool name is unique — the host registry would otherwise silently overwrite or drop a registration.',\n );\n }\n}\n\nfunction groupOwners(\n definitions: readonly DefinitionCollisionInput[],\n keysOf: (definition: DefinitionCollisionInput) => string[],\n): Map<string, string[]> {\n const owners = new Map<string, string[]>();\n for (const definition of definitions) {\n for (const key of keysOf(definition)) {\n owners.set(key, [...(owners.get(key) ?? []), definition.slug]);\n }\n }\n return owners;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"integration-definition.js","sourceRoot":"","sources":["../src/integration-definition.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The canonical integration-definition contract: ONE zod schema and ONE set\n * of inferred/hand-written types (F9). `@ekanos/sdk`'s `defineIntegration()`\n * validates against this schema at authoring time; `@kit/integrations-core`'s\n * `registerPartnerIntegration()` re-validates against the SAME schema at the\n * host trust boundary (F3). Both packages depend on this one; it depends on\n * neither, so there is no cycle and no hand-written structural twin.\n *\n * Dependency-pure (zod only): partner component refs are checked\n * structurally via `ComponentReference`, so no React dependency leaks in.\n */\nimport { z } from 'zod';\n\nimport type {\n IntegrationContext,\n StorageKeyDeclarationInput,\n StorageSchemas,\n} from './capability-context';\nimport type { ComponentReference } from './component-reference';\nimport { isComponentReference } from './component-reference';\nimport {\n type WorkspaceTargetDefinition,\n WorkspaceTargetListSchema,\n} from './workspace-target';\n\n// ---- JSON-compatible values (F4) ------------------------------------------\n\ntype JsonPrimitive = string | number | boolean | null;\nexport type JsonValue =\n | JsonPrimitive\n | JsonValue[]\n | { [key: string]: JsonValue };\n\nconst jsonValueSchema: z.ZodType<JsonValue> = z.lazy(() =>\n z.union([\n z.string(),\n // `.finite()` rejects Infinity/-Infinity AND NaN (Number.isFinite) — all\n // of which JSON.stringify silently turns to `null`, so they are not\n // JSON-compatible values (F4).\n z.number().finite(),\n z.boolean(),\n z.null(),\n z.array(jsonValueSchema),\n z.record(jsonValueSchema),\n ]),\n);\n\n// ---- Leaf validators -------------------------------------------------------\n\nfunction componentRefSchema(what: string) {\n return z.custom<ComponentReference>(isComponentReference, {\n message: `${what} must be a React component reference (a function component, or a memo/forwardRef/lazy wrapper) — pass the component itself, not an element or a module path.`,\n });\n}\n\nconst zodSchemaRef = z.custom<z.ZodType>(\n (value) =>\n typeof (value as { safeParse?: unknown } | null)?.safeParse === 'function',\n {\n message:\n 'Every storage key must declare a zod schema (e.g. z.object({ … })) — ctx.storage validates reads and writes against it (capability-context ruling 1).',\n },\n);\n\nconst nonEmpty = (what: string) =>\n z.string().min(1, { message: `${what} must be a non-empty string.` });\n\nconst slugSchema = z.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, {\n message:\n 'slug must be kebab-case ([a-z0-9] segments separated by single hyphens), e.g. \"acme-crm\" — it becomes the product slug, route segment, and MCP namespace.',\n});\n\nconst widgetIdSchema = z.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, {\n message:\n 'Widget ids are kebab-case and globally unique, e.g. \"acme-crm-pipeline\" — prefix with the integration slug to stay collision-free.',\n});\n\nconst storageKeySchema = z.string().regex(/^[a-z0-9_-]+(?:\\/[a-z0-9_-]+)?$/, {\n message:\n 'Storage keys are \"<dataType>\" or \"<dataType>/<subtype>\" in lowercase [a-z0-9_-] — they map onto the account/user product-data columns (capability-context ruling 6).',\n});\n\nconst toolNameSchema = z.string().regex(/^[a-z][a-z0-9_]*$/, {\n message:\n 'Tool names are lowercase snake_case starting with a letter, e.g. \"list_invoices\" — the model calls them by this exact string.',\n});\n\nconst webhookIdSchema = z.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, {\n message:\n 'Webhook ids are kebab-case, e.g. \"payment-updated\" — the host ingress route addresses the handler by this exact string.',\n});\n\nconst scheduleIdSchema = z.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, {\n message:\n 'Schedule ids are kebab-case, e.g. \"daily-reconcile\" — the host scheduler addresses the handler by this exact string.',\n});\n\n// Origin-only egress entries (ruling 3): absolute https origins, optional\n// `*.` subdomain wildcard, no path/query/hash/credentials/http. Kept as a\n// pure regex here so this package depends on nothing; the SDK's shared\n// `parseEgressEntry`/`isEgressAllowed` matcher enforces the identical shape\n// at runtime.\nconst egressEntrySchema = z.string().superRefine((entry, ctx) => {\n const match = /^https:\\/\\/(\\*\\.)?([a-z0-9.-]+)(?::(\\d+))?$/i.exec(entry);\n if (!match) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message:\n `Egress entry \"${entry}\" is invalid. Entries are https origins only — ` +\n `\"https://api.example.com\" (exact) or \"https://*.example.com\" ` +\n `(subdomain wildcard): scheme + host + optional port, no path, query, ` +\n `hash, credentials, or http. Fix it in the integration's egress list.`,\n });\n return;\n }\n const host = match[2] ?? '';\n if (host.includes('*') || host.startsWith('.') || host.endsWith('.')) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Egress entry \"${entry}\" has a malformed host — wildcards are only supported as a single leading \"*.\" (e.g. \"https://*.example.com\").`,\n });\n }\n});\n\n// ---- Sub-object schemas ----------------------------------------------------\n\nconst capabilitySchema = z\n .object({\n label: nonEmpty('capabilities[].label'),\n description: nonEmpty('capabilities[].description'),\n icon: componentRefSchema('capabilities[].icon').optional(),\n })\n .strict();\n\nconst permissionSchema = z\n .object({\n label: nonEmpty('permissions[].label'),\n detail: nonEmpty('permissions[].detail'),\n type: z.enum(['read', 'write']),\n })\n .strict();\n\nconst gridUnitSchema = z\n .object({\n cols: z.number().int().positive(),\n rows: z.number().int().positive(),\n })\n .strict();\n\nconst layoutBoxSchema = z\n .object({\n x: z.number(),\n y: z.number(),\n w: z.number(),\n h: z.number(),\n maxHeight: z.number().optional(),\n })\n .strict();\n\n/**\n * F7: authorable widget fields ONLY. Host-resolved fields (`productId`,\n * `widgetConfigId`, `workspaceId`, `collapsed`, `isPinned`, `health`,\n * `integrationMetadata`) are absent by design and rejected at runtime by\n * `.strict()` — the type and the runtime agree. The host adapter maps this\n * into the full `WidgetConfig`.\n */\nconst widgetSchema = z\n .object({\n id: widgetIdSchema,\n name: nonEmpty('widgets[].name'),\n component: componentRefSchema('widgets[].component'),\n widgetState: z.enum(['active', 'inactive', 'disabled']),\n gridSize: z.union([gridUnitSchema, z.array(gridUnitSchema)]).optional(),\n gridPosition: z\n .object({ col: z.number(), row: z.number() })\n .strict()\n .optional(),\n layouts: z\n .object({\n lg: layoutBoxSchema.optional(),\n md: layoutBoxSchema.optional(),\n sm: layoutBoxSchema.optional(),\n })\n .strict()\n .optional(),\n category: z\n .object({\n id: z.string(),\n name: z.string(),\n slug: z.string(),\n icon: z.string().nullable(),\n })\n .strict()\n .optional(),\n isCollapsible: z.boolean().optional(),\n isPinnable: z.boolean().optional(),\n aiFooterEnabled: z.boolean().optional(),\n })\n .strict();\n\nconst toolParametersSchema = z\n .object({\n type: z.literal('object'),\n properties: z.record(jsonValueSchema).optional(),\n required: z.array(z.string()).optional(),\n additionalProperties: z.boolean().optional(),\n })\n .strict();\n\nconst toolRunSchema = z.custom<\n (ctx: never, args: Record<string, unknown>) => Promise<unknown>\n>((value) => typeof value === 'function', {\n message:\n 'tools[].run must be a function (ctx, args) => Promise<result> — it receives the host-scoped IntegrationContext, never a raw client.',\n});\n\nconst toolSchema = z\n .object({\n name: toolNameSchema,\n description: nonEmpty('tools[].description'),\n parameters: toolParametersSchema.optional(),\n run: toolRunSchema,\n outputExample: z.record(jsonValueSchema).optional(),\n })\n .strict();\n\n// ---- Event surfaces (webhooks, schedules, OAuth) ---------------------------\n//\n// Declared exactly like MCP tools: metadata parsed strictly, handlers checked\n// structurally as functions (`z.custom`) and carried through the parse\n// untouched. The declarations are the CONTRACT; every transport — the local\n// harness today, the host's public ingress/scheduler/hosted-callback later —\n// binds to these same fields, so a partner package never changes when the\n// real transports arrive.\n\nfunction handlerSchema(what: string, shape: string) {\n return z.custom<(ctx: never, arg: never) => Promise<unknown>>(\n (value) => typeof value === 'function',\n {\n message: `${what} must be a function ${shape} — it receives the host-scoped IntegrationContext, never a raw request or client.`,\n },\n );\n}\n\nconst payloadSchemaRef = z.custom<z.ZodType>(\n (value) =>\n typeof (value as { safeParse?: unknown } | null)?.safeParse === 'function',\n {\n message:\n 'webhooks[].payloadSchema must be a zod schema (e.g. z.object({ … })) — the transport validates every delivery against it before the handler runs.',\n },\n);\n\n/**\n * How the TRANSPORT verifies a delivery. Verification is never the partner's\n * job: the declaration names the signature header and the secret that signs\n * it; the host ingress enforces it (the local harness logs it as skipped).\n * `'none'` is an explicit statement that the source is unsigned.\n */\nconst webhookSignatureSchema = z.union([\n z.literal('none'),\n z\n .object({\n header: nonEmpty('webhooks[].signature.header'),\n secretName: nonEmpty('webhooks[].signature.secretName'),\n })\n .strict(),\n]);\n\nconst webhookSchema = z\n .object({\n id: webhookIdSchema,\n description: nonEmpty('webhooks[].description'),\n payloadSchema: payloadSchemaRef,\n signature: webhookSignatureSchema,\n examplePayload: z.record(jsonValueSchema).optional(),\n handler: handlerSchema(\n 'webhooks[].handler',\n '(ctx, event) => Promise<WebhookResult>',\n ),\n })\n .strict();\n\nconst scheduleSchema = z\n .object({\n id: scheduleIdSchema,\n description: nonEmpty('schedules[].description'),\n // Presence only here — the dependency-pure schema package stays zod-only,\n // so the real 5-field cron syntax check lives in the SDK layer\n // (`defineIntegration()`), the same way it layers cross-field rules today.\n cron: nonEmpty('schedules[].cron'),\n handler: handlerSchema(\n 'schedules[].handler',\n '(ctx, invocation) => Promise<ScheduleResult>',\n ),\n })\n .strict();\n\nconst httpsUrlSchema = (what: string) =>\n z.string().superRefine((value, ctx) => {\n let parsed: URL;\n try {\n parsed = new URL(value);\n } catch {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `${what} must be an absolute URL, e.g. \"https://provider.example/oauth/authorize\".`,\n });\n return;\n }\n if (parsed.protocol !== 'https:') {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `${what} must use https — OAuth endpoints are never plain http.`,\n });\n }\n if (parsed.username !== '' || parsed.password !== '') {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `${what} must not embed credentials.`,\n });\n }\n });\n\nconst oauthSchema = z\n .object({\n provider: z\n .object({\n authorizationUrl: httpsUrlSchema('oauth.provider.authorizationUrl'),\n tokenUrl: httpsUrlSchema('oauth.provider.tokenUrl'),\n scopes: z.array(nonEmpty('oauth.provider.scopes[]')),\n pkce: z.boolean().optional(),\n })\n .strict(),\n credentials: z\n .object({\n clientIdSecretName: nonEmpty('oauth.credentials.clientIdSecretName'),\n clientSecretSecretName: nonEmpty(\n 'oauth.credentials.clientSecretSecretName',\n ),\n })\n .strict(),\n onTokens: handlerSchema('oauth.onTokens', '(ctx, tokens) => Promise<void>'),\n })\n .strict();\n\nconst toolClassificationProposalSchema = z\n .object({\n effect: z.enum(['read', 'write']).optional(),\n sensitivity: z.enum(['public', 'internal', 'pii', 'financial']).optional(),\n })\n .strict();\n\nconst proposalsSchema = z\n .object({\n credentialModel: z.enum(['account', 'user', 'source']).optional(),\n tools: z.record(toolClassificationProposalSchema).optional(),\n })\n .strict();\n\n/**\n * A storage key's EXPLICIT declaration: the zod schema plus its exposure\n * flags. `clientReadable` is the only way a declared key becomes readable by\n * the browser through the generic storage route — and it defaults to false,\n * so the bare-schema form stays server-only exactly as it always was.\n * `.strict()` keeps an unrecognized flag (a typo like `clientReadible`) an\n * error rather than a silently-ignored key whose author believes it is\n * exposed — or, worse, believes it is not.\n */\nconst storageKeyDeclarationSchema = z\n .object({\n schema: zodSchemaRef,\n clientReadable: z.boolean().optional(),\n })\n .strict();\n\n/** Duck-typed so a partner's own bundled zod copy still reads as a schema. */\nfunction isZodSchemaLike(value: unknown): boolean {\n return (\n typeof (value as { safeParse?: unknown } | null)?.safeParse === 'function'\n );\n}\n\n/**\n * Either declaration form, hand-routed rather than expressed as `z.union` so\n * the failure message stays specific. A union reports a bare \"Invalid input\"\n * for every wrong shape, which would lose both the \"declare a zod schema\"\n * guidance AND the strict-descriptor typo report — the two errors an author\n * is actually going to hit.\n */\nconst storageKeyDeclarationRef = z\n .custom<StorageKeyDeclarationInput>(() => true)\n .superRefine((value, ctx) => {\n if (isZodSchemaLike(value)) return;\n\n const looksLikeDescriptor =\n value !== null && typeof value === 'object' && !Array.isArray(value);\n\n // Neither form: name both, since the descriptor is the less obvious one.\n if (\n !looksLikeDescriptor ||\n !isZodSchemaLike((value as { schema?: unknown }).schema)\n ) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message:\n 'Every storage key must declare either a zod schema (e.g. z.object({ … })) or a { schema, clientReadable } descriptor — ctx.storage validates reads and writes against the schema (capability-context ruling 1), and clientReadable (default false) is what opts the key in to the browser-readable storage route.',\n });\n return;\n }\n\n // A real descriptor with a real schema — report its own issues verbatim\n // (an unrecognized flag, a non-boolean clientReadable) rather than the\n // generic message, which would send the author looking in the wrong place.\n const result = storageKeyDeclarationSchema.safeParse(value);\n if (result.success) return;\n\n for (const issue of result.error.issues) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: issue.path,\n message: issue.message,\n });\n }\n });\n\nconst storageScopeSchema = z.record(storageKeySchema, storageKeyDeclarationRef);\n\nconst componentsSchema = z\n .object({\n activationForm: componentRefSchema('components.activationForm').optional(),\n marketplaceTile: componentRefSchema(\n 'components.marketplaceTile',\n ).optional(),\n widgets: z.array(widgetSchema).optional(),\n })\n .strict();\n\n/**\n * THE canonical schema. Strict everywhere: an unrecognized key is an error,\n * which is what keeps host-assigned fields (productId, kind, trust tier,\n * credentialModel, per-tool effect/sensitivity, host-resolved widget fields)\n * structurally un-settable at runtime, not merely absent from the type.\n */\nexport const IntegrationDefinitionSchema = z\n .object({\n slug: slugSchema,\n name: nonEmpty('name'),\n description: nonEmpty('description'),\n version: z\n .string()\n .regex(\n /^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$/,\n {\n message:\n 'version must be semver (\"1.0.0\", optionally with a prerelease/build suffix) — promotion diffs definitions by it.',\n },\n ),\n capabilities: z.array(capabilitySchema).optional(),\n permissions: z.array(permissionSchema).optional(),\n components: componentsSchema.optional(),\n workspaceTargets: WorkspaceTargetListSchema.optional(),\n tools: z.array(toolSchema).optional(),\n storage: z\n .object({\n account: storageScopeSchema.optional(),\n user: storageScopeSchema.optional(),\n })\n .strict()\n .optional(),\n egress: z.array(egressEntrySchema).optional(),\n webhooks: z.array(webhookSchema).optional(),\n schedules: z.array(scheduleSchema).optional(),\n oauth: oauthSchema.optional(),\n proposes: proposalsSchema.optional(),\n })\n .strict()\n .superRefine((definition, ctx) => {\n const webhookIds = (definition.webhooks ?? []).map((w) => w.id);\n for (const id of findDuplicates(webhookIds)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['webhooks'],\n message: `Webhook id \"${id}\" is declared more than once — give every webhook a unique id.`,\n });\n }\n\n const scheduleIds = (definition.schedules ?? []).map((s) => s.id);\n for (const id of findDuplicates(scheduleIds)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['schedules'],\n message: `Schedule id \"${id}\" is declared more than once — give every schedule a unique id.`,\n });\n }\n\n const widgetIds = (definition.components?.widgets ?? []).map((w) => w.id);\n for (const id of findDuplicates(widgetIds)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['components', 'widgets'],\n message: `Widget id \"${id}\" is declared more than once — give every widget a unique id.`,\n });\n }\n\n const toolNames = (definition.tools ?? []).map((tool) => tool.name);\n for (const name of findDuplicates(toolNames)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['tools'],\n message: `Tool \"${name}\" is declared more than once — give every tool a unique name.`,\n });\n }\n\n const declaredTools = new Set(toolNames);\n for (const proposedName of Object.keys(definition.proposes?.tools ?? {})) {\n if (!declaredTools.has(proposedName)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n path: ['proposes', 'tools', proposedName],\n message: `proposes.tools[\"${proposedName}\"] does not match any declared tool — proposals are keyed by the exact tool name in \\`tools\\`.`,\n });\n }\n }\n });\n\n// ---- Hand-written generic types (the parts a non-generic schema cannot\n// express) plus inferred types for everything else. One home, imported by\n// both @ekanos/sdk and @kit/integrations-core. -------------------------------\n\nexport type ToolClassificationProposal = z.infer<\n typeof toolClassificationProposalSchema\n>;\nexport type IntegrationProposals = z.infer<typeof proposalsSchema>;\nexport type PartnerToolParameters = z.infer<typeof toolParametersSchema>;\nexport type IntegrationCapabilityDeclaration = z.infer<typeof capabilitySchema>;\nexport type IntegrationPermissionDeclaration = z.infer<typeof permissionSchema>;\nexport type PartnerWidgetDeclaration = z.infer<typeof widgetSchema>;\n\nexport interface PartnerToolModule<\n Schemas extends StorageSchemas = StorageSchemas,\n> {\n name: string;\n description: string;\n parameters?: PartnerToolParameters;\n /**\n * Contravariant function property (F8): the declared `Schemas` generic\n * types `ctx.storage` for the author. The generic cannot survive the\n * by-value, monomorphic host registration boundary — the adapter erases it\n * — but nothing rests on it surviving: the host constructs `ctx` FROM the\n * definition's own `storage` schemas, and `ctx.storage` validates every\n * read/write against them at runtime regardless of the handler's\n * annotation. The static generic is DX; the runtime schema is the guard.\n */\n run: (\n ctx: IntegrationContext<Schemas>,\n args: Record<string, unknown>,\n ) => Promise<unknown>;\n outputExample?: Record<string, JsonValue>;\n}\n\nexport interface IntegrationComponentDeclarations {\n activationForm?: ComponentReference;\n marketplaceTile?: ComponentReference;\n widgets?: PartnerWidgetDeclaration[];\n}\n\n// ---- Event-surface types (webhooks, schedules, OAuth) ----------------------\n//\n// Hand-written generics like `PartnerToolModule`: the `Schemas` generic types\n// `ctx.storage` for the author and is erased at the host boundary, where the\n// runtime storage validator — built from the definition's own `storage`\n// schemas — is the guard.\n\n/**\n * How the transport verifies a webhook delivery. `'none'` states explicitly\n * that the source is unsigned; otherwise the transport reads the named header\n * and verifies it against the named secret. Verification is the TRANSPORT's\n * job (the local harness logs it as skipped; the host ingress enforces it) —\n * never the partner handler's.\n */\nexport type WebhookSignatureDeclaration =\n | 'none'\n | { header: string; secretName: string };\n\n/**\n * One delivery, as the handler receives it: transport-assigned id and receipt\n * time, the delivery headers, and the payload ALREADY parsed and validated\n * against the declaration's `payloadSchema`. A payload that fails the schema\n * never reaches the handler.\n */\nexport interface WebhookEvent {\n id: string;\n /** ISO-8601 — when the transport accepted the delivery. */\n receivedAt: string;\n headers: Record<string, string>;\n /** The parsed, schema-validated payload (output of `payloadSchema`). */\n payload: unknown;\n}\n\n/**\n * What the handler tells the transport. `processed` acknowledges the event;\n * `ignored` acknowledges it as irrelevant (still a 2xx — the sender must not\n * retry). A handler that cannot process a valid event THROWS, which the\n * transport maps to a retryable failure.\n */\nexport interface WebhookResult {\n status: 'processed' | 'ignored';\n detail?: string;\n}\n\nexport interface PartnerWebhookDeclaration<\n Schemas extends StorageSchemas = StorageSchemas,\n> {\n id: string;\n description: string;\n /** Validates every delivery before the handler runs. */\n payloadSchema: z.ZodType;\n signature: WebhookSignatureDeclaration;\n /**\n * A representative payload, JSON-compatible. Seeds the harness's payload\n * editor and documents the shape beside the schema.\n */\n examplePayload?: Record<string, JsonValue>;\n handler: (\n ctx: IntegrationContext<Schemas>,\n event: WebhookEvent,\n ) => Promise<WebhookResult>;\n}\n\n/**\n * One firing, as the handler receives it. `trigger` distinguishes the real\n * scheduler from a human pressing \"Run now\" (harness or admin) — handlers may\n * branch on it (e.g. skip idempotency windows for manual runs) but must be\n * safe under both.\n */\nexport interface ScheduleInvocation {\n /** ISO-8601 — the tick this invocation stands for. */\n scheduledFor: string;\n /** ISO-8601 — when the handler actually started. */\n invokedAt: string;\n trigger: 'schedule' | 'manual';\n}\n\n/**\n * `completed` means the run did its work; `skipped` means it correctly did\n * nothing (not configured, nothing to do). A handler that fails THROWS, which\n * the transport records as a failed run.\n */\nexport interface ScheduleResult {\n status: 'completed' | 'skipped';\n detail?: string;\n}\n\nexport interface PartnerScheduleDeclaration<\n Schemas extends StorageSchemas = StorageSchemas,\n> {\n id: string;\n description: string;\n /**\n * Standard 5-field cron (minute hour day-of-month month day-of-week),\n * validated by `defineIntegration()`. The schema package checks presence\n * only — full syntax validation is the SDK layer's job.\n */\n cron: string;\n handler: (\n ctx: IntegrationContext<Schemas>,\n invocation: ScheduleInvocation,\n ) => Promise<ScheduleResult>;\n}\n\n/**\n * The token set the transport hands `onTokens` after a code exchange (and\n * after each refresh). `raw` carries provider-specific extras verbatim.\n */\nexport interface OAuthTokens {\n accessToken: string;\n refreshToken?: string;\n /** ISO-8601 expiry, when the provider reports one. */\n expiresAt?: string;\n scope?: string;\n tokenType?: string;\n raw?: Record<string, JsonValue>;\n}\n\nexport interface OAuthProviderDeclaration {\n authorizationUrl: string;\n tokenUrl: string;\n scopes: string[];\n pkce?: boolean;\n}\n\n/**\n * The OAuth contract. The TRANSPORT owns the flow (authorize redirect, state,\n * callback, code exchange — localhost in the harness, hosted later); the\n * partner declares the provider endpoints, names the client-credential\n * secrets, and persists tokens in `onTokens` via `ctx.secrets` — so token\n * storage policy is the existing capability layer, nothing new.\n * `defineIntegration()` rejects the declaration unless both endpoint origins\n * are covered by the definition's `egress` list.\n */\nexport interface PartnerOAuthDeclaration<\n Schemas extends StorageSchemas = StorageSchemas,\n> {\n provider: OAuthProviderDeclaration;\n credentials: {\n clientIdSecretName: string;\n clientSecretSecretName: string;\n };\n onTokens: (\n ctx: IntegrationContext<Schemas>,\n tokens: OAuthTokens,\n ) => Promise<void>;\n}\n\nexport interface IntegrationDefinition<\n Schemas extends StorageSchemas = StorageSchemas,\n> {\n slug: string;\n name: string;\n description: string;\n version: string;\n capabilities?: IntegrationCapabilityDeclaration[];\n permissions?: IntegrationPermissionDeclaration[];\n components?: IntegrationComponentDeclarations;\n workspaceTargets?: WorkspaceTargetDefinition[];\n tools?: PartnerToolModule<Schemas>[];\n storage?: Schemas;\n egress?: string[];\n webhooks?: PartnerWebhookDeclaration<Schemas>[];\n schedules?: PartnerScheduleDeclaration<Schemas>[];\n oauth?: PartnerOAuthDeclaration<Schemas>;\n proposes?: IntegrationProposals;\n}\n\n// ---- Shared helpers --------------------------------------------------------\n\nfunction findDuplicates(values: readonly string[]): string[] {\n const seen = new Set<string>();\n const duplicates = new Set<string>();\n for (const value of values) {\n if (seen.has(value)) duplicates.add(value);\n seen.add(value);\n }\n return [...duplicates];\n}\n\nconst HOST_ASSIGNED_REMINDER =\n 'Host-assigned fields are never partner-authorable: productId, kind, trust ' +\n 'tier, and machine exposure (credentialModel) do not exist on ' +\n 'IntegrationDefinition, per-tool effect/sensitivity belong in the ' +\n '`proposes` block, and host-resolved widget fields (productId, ' +\n 'widgetConfigId, workspaceId, collapsed, isPinned, health, ' +\n 'integrationMetadata) are populated by the platform at runtime — remove ' +\n 'them from the definition.';\n\n// ---- Structured findings (non-throwing validation surface) -----------------\n\n/**\n * One structured validation result. This is the committed shape the CLI and\n * any other tooling consumes — the collectors below return arrays of these,\n * and the throwing entry points (`parseIntegrationDefinition`,\n * `validateIntegrationDefinitions`) are built on the exact same rules so there\n * is one rule set, not two.\n *\n * `line` is deliberately optional and usually ABSENT: zod reports a `path`\n * (`components.widgets[2].id`), not a byte offset into a source file, and\n * fabricating a line number would be a lie. The zod path lives in `message`;\n * `file` names the module the definition was loaded from when the caller knows\n * it. `hint` is always a non-empty, imperative remediation instruction.\n */\nexport interface Finding {\n check: string;\n severity: 'error' | 'warn' | 'info';\n file?: string;\n line?: number;\n message: string;\n hint: string;\n}\n\nexport interface CollectDefinitionOptions {\n /** The module the definition was loaded from, stamped onto every finding. */\n file?: string;\n}\n\nconst PLAIN_DATA_HINT =\n 'Declarations must be finite plain data. Remove the cycle, getter/setter, ' +\n 'or class/exotic instance the message names so the value cannot change ' +\n 'after validation, then re-run validate.';\n\n/** Per-issue remediation. Unrecognized keys get the host-assigned reminder. */\nfunction hintForIssue(issue: z.ZodIssue): string {\n if (issue.code === z.ZodIssueCode.unrecognized_keys) {\n return HOST_ASSIGNED_REMINDER;\n }\n const path = issue.path.length > 0 ? issue.path.join('.') : '(root)';\n return (\n `Correct the value at \"${path}\" so it satisfies ` +\n `@ekanos/integration-schema's IntegrationDefinitionSchema, then re-run ` +\n `validate.`\n );\n}\n\n/**\n * The single, shared implementation behind BOTH the non-throwing collector and\n * the throwing `parseIntegrationDefinition`. Runs the plain-data structural\n * check first (short-circuiting exactly as the throwing path always has), then\n * the canonical zod parse. Returns the findings, the sanitized `data` on\n * success, and whether an unrecognized key was among the failures (the\n * throwing path appends the host-assigned reminder only in that case).\n */\nfunction collectDefinitionResult(\n input: unknown,\n options: CollectDefinitionOptions = {},\n): {\n findings: Finding[];\n data?: IntegrationDefinition;\n hasUnrecognizedKey: boolean;\n} {\n const { file } = options;\n\n // Structural pre-check: the same rule assertPlainDeclaration throws on, but\n // captured as a finding. If it fails we stop here, matching the throwing\n // path which never reaches safeParse once the pre-check throws.\n try {\n assertPlainDeclaration(input);\n } catch (error) {\n return {\n findings: [\n {\n check: 'definition.plain-data',\n severity: 'error',\n ...(file ? { file } : {}),\n message: error instanceof Error ? error.message : String(error),\n hint: PLAIN_DATA_HINT,\n },\n ],\n hasUnrecognizedKey: false,\n };\n }\n\n const result = IntegrationDefinitionSchema.safeParse(input);\n if (result.success) {\n deepFreezeDefinition(result.data);\n return {\n findings: [],\n data: result.data as unknown as IntegrationDefinition,\n hasUnrecognizedKey: false,\n };\n }\n\n const hasUnrecognizedKey = result.error.issues.some(\n (issue) => issue.code === z.ZodIssueCode.unrecognized_keys,\n );\n\n const findings = result.error.issues.map((issue): Finding => {\n const path = issue.path.length > 0 ? issue.path.join('.') : '(root)';\n return {\n check: 'definition.schema',\n severity: 'error',\n ...(file ? { file } : {}),\n // The zod path, not a source line — see the Finding doc comment.\n message: `${path}: ${issue.message}`,\n hint: hintForIssue(issue),\n };\n });\n\n return { findings, hasUnrecognizedKey };\n}\n\n/**\n * Non-throwing sibling of `parseIntegrationDefinition`: validates a single\n * integration definition against the canonical schema and returns structured\n * findings instead of throwing a pre-formatted string. An empty array means\n * the definition is valid. Used by `@ekanos/cli validate`.\n */\nexport function collectDefinitionFindings(\n input: unknown,\n options: CollectDefinitionOptions = {},\n): Finding[] {\n return collectDefinitionResult(input, options).findings;\n}\n\n/**\n * A zod schema (storage leaf) or a React exotic (`memo`/`forwardRef`, an\n * object tagged with `$$typeof`). NOTHING here reads a property value:\n * `instanceof` walks the prototype chain and `in` is [[HasProperty]], so a\n * malicious getter still cannot execute during leaf detection (F4).\n *\n * `instanceof z.ZodType` alone is NOT sufficient. It answers \"is this an\n * instance of THIS package's zod copy\", and a partner's `zod` is routinely a\n * different copy — any transitive dependency pinning a different range, or a\n * package manager that nests instead of deduping, is enough. When the copies\n * differ, `instanceof` is false, `assertPlainDeclaration` walks INTO the\n * schema, and every storage key is rejected as \"a class/exotic instance, not\n * a plain object\" — an error that says nothing about the real cause and sends\n * the author looking at an object literal that is already correct.\n *\n * So structural detection is the fallback, matching the duck-typing\n * `isZodSchemaLike` already does one layer down for exactly this reason.\n * `~standard` is the Standard Schema marker (zod >= 3.24); `_def` +\n * `safeParse` covers older copies. This widens nothing security-relevant: a\n * value that clears this check still has to satisfy `zodSchemaRef` /\n * `storageKeyDeclarationRef`, which call `.safeParse` regardless, and the\n * re-parse at the host trust boundary remains the real guard.\n */\nfunction isDeclarationLeaf(value: object): boolean {\n if (value instanceof z.ZodType) return true;\n if ('$$typeof' in value) return true;\n\n return '~standard' in value || ('_def' in value && 'safeParse' in value);\n}\n\n/**\n * F4: reject accessor/proxy/class-instance/cyclic declaration containers\n * before parsing. An object with getters (or a proxy) can return validated\n * values during parse and different values later; a non-plain prototype can\n * smuggle mutable state past `z.object()`; a cycle would recurse into zod\n * rather than fail cleanly. We walk every CONTAINER (plain object / array),\n * and stop at legitimate leaves: functions (component refs, `run`) and zod\n * schemas (storage). Leaf detection happens BEFORE any own-property read, so\n * a `safeParse` getter cannot execute. Proxy detection is best-effort — the\n * re-parse at the host boundary (which materializes fresh values via zod) is\n * the real guard.\n *\n * Cycle detection tracks the ANCESTOR chain only (add on enter, remove on\n * exit): a genuine back-edge is a cycle, but the same object referenced from\n * two sibling branches (a DAG — e.g. a shallow-cloned widget sharing a\n * `layouts` object) is not, and must not be rejected.\n */\nexport function assertPlainDeclaration(\n value: unknown,\n path = '(root)',\n ancestors: WeakSet<object> = new WeakSet(),\n): void {\n if (value === null || typeof value !== 'object') return;\n\n if (typeof value === 'function') return;\n\n // Leaf detection first — instanceof / HasProperty never invoke a getter.\n if (isDeclarationLeaf(value)) return;\n\n if (ancestors.has(value)) {\n throw new Error(\n `Integration definition contains a cycle at ${path}. ` +\n `Declarations must be finite plain data — remove the self-reference.`,\n );\n }\n\n const proto = Object.getPrototypeOf(value) as unknown;\n const isArray = Array.isArray(value);\n if (!isArray && proto !== Object.prototype && proto !== null) {\n throw new Error(\n `Integration definition value at ${path} is a class/exotic instance, not a plain object. ` +\n `Declaration containers must be plain object/array literals so their values cannot mutate after validation.`,\n );\n }\n\n ancestors.add(value);\n for (const key of Object.keys(value)) {\n const descriptor = Object.getOwnPropertyDescriptor(value, key);\n if (descriptor && (descriptor.get || descriptor.set)) {\n throw new Error(\n `Integration definition property at ${path}.${key} is a getter/setter, not a data property. ` +\n `Declaration values must be plain data — a getter can return a different value after validation.`,\n );\n }\n assertPlainDeclaration(\n (value as Record<string, unknown>)[key],\n `${path}.${key}`,\n ancestors,\n );\n }\n ancestors.delete(value);\n}\n\nconst frozen = new WeakSet<object>();\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n if (value === null || typeof value !== 'object') return false;\n const proto = Object.getPrototypeOf(value) as unknown;\n return proto === Object.prototype || proto === null;\n}\n\n/**\n * Cycle-aware deep freeze (F4). Freezes plain objects and arrays; leaves zod\n * schemas (freezing breaks their internal caches) and functions alone.\n */\nexport function deepFreezeDefinition(value: unknown): void {\n if (value === null || typeof value !== 'object') return;\n if (frozen.has(value)) return;\n\n if (Array.isArray(value)) {\n frozen.add(value);\n Object.freeze(value);\n for (const item of value) deepFreezeDefinition(item);\n return;\n }\n if (isPlainObject(value)) {\n frozen.add(value);\n Object.freeze(value);\n for (const item of Object.values(value)) deepFreezeDefinition(item);\n }\n}\n\n/**\n * The single validation entry point used by BOTH `defineIntegration()` (SDK,\n * authoring time) and `registerPartnerIntegration()` (core, host trust\n * boundary — F3). Rejects non-plain containers, then parses against the\n * canonical schema, and returns the SANITIZED `result.data` (fresh, plain,\n * strict-stripped — never the caller's original object). Throws an Error\n * whose message is a remediation instruction.\n */\nexport function parseIntegrationDefinition(\n input: unknown,\n): IntegrationDefinition {\n // Built ON TOP of the collector so there is exactly one rule set. The\n // collector runs assertPlainDeclaration first (short-circuiting), then the\n // canonical parse, and freezes `data` on success (F4) — so a successful\n // result here is already the deep-frozen, sanitized definition.\n const { findings, data, hasUnrecognizedKey } = collectDefinitionResult(input);\n\n if (data) {\n // The schema's inferred output matches IntegrationDefinition in every\n // non-generic field; the storage/tool generics default to the permissive\n // base, which is exactly right for the loose registration boundary.\n return data;\n }\n\n // A plain-data structural failure is thrown verbatim (its message is already\n // a remediation: \"…contains a cycle…\", \"…is a getter/setter…\").\n const plainDataFinding = findings.find(\n (finding) => finding.check === 'definition.plain-data',\n );\n if (plainDataFinding) {\n throw new Error(plainDataFinding.message);\n }\n\n // Schema failures reproduce the historical message shape exactly: each\n // finding's message is already `${path}: ${issue.message}`, so re-prefixing\n // with ` - ` reconstructs formatIssues() verbatim.\n const slug =\n typeof (input as { slug?: unknown } | null)?.slug === 'string'\n ? ` for \"${(input as { slug: string }).slug}\"`\n : '';\n // The reminder is six lines about fields the author may not have written.\n // Appending it to EVERY failure buries the one line that matters — a bad\n // semver or a malformed cron arrives under a paragraph about productId and\n // trust tiers. Show it only when an unrecognized key is what failed, which\n // is the case it was written for.\n throw new Error(\n `Invalid integration definition${slug}:\\n` +\n findings.map((finding) => ` - ${finding.message}`).join('\\n') +\n (hasUnrecognizedKey ? `\\n${HOST_ASSIGNED_REMINDER}` : ''),\n );\n}\n\n// ---- Cross-definition collision detection (F5) -----------------------------\n\n/**\n * THE canonical effective MCP tool name — the single source of truth for how\n * discovery keys a tool. Tool discovery namespaces each raw tool name with the\n * integration slug (`slug.replace(/-/g,'_')`), skipping the prefix when the\n * name already carries it. Two collision-free RAW pairs can therefore collapse\n * to the same EFFECTIVE name (`{slug:\"foo\",tool:\"bar_baz\"}` and\n * `{slug:\"foo-bar\",tool:\"baz\"}` both become `foo_bar_baz`), so collision\n * checking MUST compare effective names, and runtime discovery MUST throw on a\n * duplicate assignment. Both call this one helper\n * (`packages/agents/src/tools/tool-discovery.ts`).\n */\nexport function getDiscoveredToolName(slug: string, rawName: string): string {\n const slugPrefix = slug.replace(/-/g, '_');\n return rawName.startsWith(slugPrefix) ? rawName : `${slugPrefix}_${rawName}`;\n}\n\n/**\n * The metadata-only shape collision checking needs — no handlers, no schemas\n * (F8: collision validation must not force widening the tool handlers). A\n * full `IntegrationDefinition` is assignable to it.\n */\nexport interface DefinitionCollisionInput {\n slug: string;\n components?: { widgets?: readonly { id: string }[] } | null;\n tools?: readonly { name: string }[] | null;\n}\n\n/**\n * First-party identifiers a partner definition must not collide with (F5).\n * Widget lookup matches on `widget.id` and the assistant's tool list is a\n * flat name-keyed map where a later registration overwrites an earlier one,\n * so a partner reusing a first-party id/name silently hijacks it. Sourced\n * from the reviewed registry inventory, not from executing partner handlers.\n */\nexport interface FirstPartyInventory {\n slugs?: readonly string[];\n widgetIds?: readonly string[];\n /**\n * EFFECTIVE (discovery) tool names — `getDiscoveredToolName(slug, rawName)` —\n * NOT raw names, since discovery keys the flat registry by the effective name.\n */\n toolNames?: readonly string[];\n}\n\n/**\n * Detects cross-definition collisions (duplicate slugs, widget ids, tool\n * names across the partner set) AND collisions against the first-party\n * inventory, throwing one error listing EVERY collision.\n *\n * This is the build-time gate the host registry deliberately lacks:\n * `integrationRegistry.register()` keys by slug via `Map.set` and silently\n * OVERWRITES, and duplicate widget/tool ids resolve last- or\n * first-registration-wins by import order.\n */\n/**\n * One collision, split into the human `message` (unchanged from the strings\n * this module has always produced — callers and tests match on fragments like\n * `effective tool name \"foo_bar_baz\"`) and a separate imperative `hint`.\n */\ninterface CollisionRecord {\n check: string;\n message: string;\n hint: string;\n}\n\n/**\n * THE shared collision rule set, returning structured records. Both the\n * throwing `validateIntegrationDefinitions` and the non-throwing\n * `collectCollisionFindings` are built on this, so there is one rule set.\n */\nfunction computeCollisionRecords(\n definitions: readonly DefinitionCollisionInput[],\n firstParty: FirstPartyInventory = {},\n): CollisionRecord[] {\n const slugCounts = new Map<string, number>();\n const widgetOwners = new Map<string, string[]>();\n const toolOwners = new Map<string, string[]>();\n\n for (const definition of definitions) {\n slugCounts.set(definition.slug, (slugCounts.get(definition.slug) ?? 0) + 1);\n for (const widget of definition.components?.widgets ?? []) {\n widgetOwners.set(widget.id, [\n ...(widgetOwners.get(widget.id) ?? []),\n definition.slug,\n ]);\n }\n for (const tool of definition.tools ?? []) {\n // EFFECTIVE (discovery) name, not the raw name — two collision-free raw\n // names can collapse to the same effective key.\n const effective = getDiscoveredToolName(definition.slug, tool.name);\n toolOwners.set(effective, [\n ...(toolOwners.get(effective) ?? []),\n definition.slug,\n ]);\n }\n }\n\n const records: CollisionRecord[] = [];\n\n for (const [slug, count] of slugCounts) {\n if (count > 1) {\n records.push({\n check: 'collision.slug',\n message: `slug \"${slug}\" is declared by ${count} partner definitions — slugs are the registry key and must be globally unique.`,\n hint: `Rename all but one of the definitions declaring slug \"${slug}\" so every slug is globally unique.`,\n });\n }\n }\n for (const [id, owners] of widgetOwners) {\n if (owners.length > 1) {\n records.push({\n check: 'collision.widget-id',\n message: `widget id \"${id}\" is declared by [${owners.join(', ')}] — widget ids are global (widget_config rows key on them); prefix yours with the integration slug.`,\n hint: `Prefix widget id \"${id}\" with your integration slug so it is globally unique.`,\n });\n }\n }\n for (const [name, owners] of toolOwners) {\n if (owners.length > 1) {\n records.push({\n check: 'collision.tool-name',\n message: `effective tool name \"${name}\" is declared by [${owners.join(', ')}] — discovery namespaces tool names by slug, so these collapse to one flat key and overwrite each other. Rename so the slug-prefixed names differ.`,\n hint: `Rename the colliding tools so their slug-prefixed effective names differ from \"${name}\".`,\n });\n }\n }\n\n const reservedSlugs = new Set(firstParty.slugs ?? []);\n const reservedWidgets = new Set(firstParty.widgetIds ?? []);\n const reservedTools = new Set(firstParty.toolNames ?? []);\n\n for (const [slug, owners] of groupOwners(definitions, (d) => [d.slug])) {\n if (reservedSlugs.has(slug)) {\n records.push({\n check: 'collision.reserved-slug',\n message: `slug \"${slug}\" (declared by [${owners.join(', ')}]) collides with a first-party integration — pick a slug no built-in product uses.`,\n hint: `Choose a different slug than \"${slug}\" — it is reserved by a first-party integration.`,\n });\n }\n }\n for (const [id, owners] of widgetOwners) {\n if (reservedWidgets.has(id)) {\n records.push({\n check: 'collision.reserved-widget-id',\n message: `widget id \"${id}\" (declared by [${owners.join(', ')}]) collides with a first-party widget — the dashboard resolves widgets by id, so this would hijack it. Prefix with the integration slug.`,\n hint: `Prefix widget id \"${id}\" with your integration slug — it is reserved by a first-party widget.`,\n });\n }\n }\n for (const [name, owners] of toolOwners) {\n if (reservedTools.has(name)) {\n records.push({\n check: 'collision.reserved-tool-name',\n message: `effective tool name \"${name}\" (declared by [${owners.join(', ')}]) collides with a first-party tool — the flat, slug-namespaced tool registry would overwrite one with the other. Rename it.`,\n hint: `Rename the tool so its effective name is not \"${name}\" — that name is reserved by a first-party tool.`,\n });\n }\n }\n\n return records;\n}\n\n/**\n * Non-throwing sibling of `validateIntegrationDefinitions`: returns structured\n * collision findings across the partner set (and against the first-party\n * inventory) instead of throwing. An empty array means no collisions. Used by\n * `@ekanos/cli validate`.\n */\nexport function collectCollisionFindings(\n definitions: readonly DefinitionCollisionInput[],\n firstParty: FirstPartyInventory = {},\n): Finding[] {\n return computeCollisionRecords(definitions, firstParty).map(\n (record): Finding => ({\n check: record.check,\n severity: 'error',\n message: record.message,\n hint: record.hint,\n }),\n );\n}\n\nexport function validateIntegrationDefinitions(\n definitions: readonly DefinitionCollisionInput[],\n firstParty: FirstPartyInventory = {},\n): void {\n const collisions = computeCollisionRecords(definitions, firstParty).map(\n (record) => record.message,\n );\n\n if (collisions.length > 0) {\n throw new Error(\n `Integration definitions collide (${collisions.length} collision${collisions.length === 1 ? '' : 's'}):\\n` +\n collisions.map((line) => ` - ${line}`).join('\\n') +\n '\\nRename until every slug, widget id, and tool name is unique — the host registry would otherwise silently overwrite or drop a registration.',\n );\n }\n}\n\nfunction groupOwners(\n definitions: readonly DefinitionCollisionInput[],\n keysOf: (definition: DefinitionCollisionInput) => string[],\n): Map<string, string[]> {\n const owners = new Map<string, string[]>();\n for (const definition of definitions) {\n for (const key of keysOf(definition)) {\n owners.set(key, [...(owners.get(key) ?? []), definition.slug]);\n }\n }\n return owners;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ekanos/integration-schema",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Canonical, dependency-pure zod schema + types for Ekanos integration definitions. Depended on by @ekanos/sdk and @kit/integrations-core; depends on neither, so there is no cycle and there is exactly one schema, one inferred type.",
|
|
6
6
|
"license": "MIT",
|
|
7
|
-
"repository": {
|
|
8
|
-
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/companydotcom/fusion.git",
|
|
10
|
-
"directory": "packages/integration-schema"
|
|
11
|
-
},
|
|
12
|
-
"homepage": "https://github.com/companydotcom/fusion/tree/dev/packages/integration-schema#readme",
|
|
13
7
|
"bugs": {
|
|
14
|
-
"
|
|
8
|
+
"email": "npm@govastly.com"
|
|
15
9
|
},
|
|
16
10
|
"files": [
|
|
17
11
|
"dist",
|