@ekanos/cli 0.18.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/commands/add.js +1 -1
  2. package/dist/commands/add.js.map +1 -1
  3. package/dist/commands/audiences.d.ts +5 -3
  4. package/dist/commands/audiences.js +6 -4
  5. package/dist/commands/audiences.js.map +1 -1
  6. package/dist/commands/scope-notice.d.ts +5 -4
  7. package/dist/commands/scope-notice.js +22 -11
  8. package/dist/commands/scope-notice.js.map +1 -1
  9. package/dist/commands/sync.js +2 -2
  10. package/dist/commands/sync.js.map +1 -1
  11. package/dist/commands/teams-audience.d.ts +11 -2
  12. package/dist/commands/teams-audience.js +22 -7
  13. package/dist/commands/teams-audience.js.map +1 -1
  14. package/dist/commands/teams-lifecycle.js +8 -2
  15. package/dist/commands/teams-lifecycle.js.map +1 -1
  16. package/dist/experience/contract-sources.d.ts +7 -2
  17. package/dist/experience/contract-sources.js +15 -8
  18. package/dist/experience/contract-sources.js.map +1 -1
  19. package/dist/experience/definition-checks.js +4 -1
  20. package/dist/experience/definition-checks.js.map +1 -1
  21. package/dist/experience/definition-shape.d.ts +2 -0
  22. package/dist/experience/definition-shape.js.map +1 -1
  23. package/dist/experience/project.js +8 -2
  24. package/dist/experience/project.js.map +1 -1
  25. package/dist/index.js +13 -9
  26. package/dist/index.js.map +1 -1
  27. package/dist/team-lifecycle-api.d.ts +30 -0
  28. package/dist/team-lifecycle-api.js +2 -0
  29. package/dist/team-lifecycle-api.js.map +1 -1
  30. package/dist/teams-api.js +29 -24
  31. package/dist/teams-api.js.map +1 -1
  32. package/package.json +2 -2
  33. package/templates/experience/package.json.tmpl +4 -4
  34. package/templates/package.json.tmpl +4 -4
@@ -377,10 +377,16 @@ export async function confirmChange(ctx, args, confirm) {
377
377
  function groupRow(group) {
378
378
  var _a;
379
379
  return [
380
- group.name,
380
+ group.kind === 'predefined'
381
+ ? `${group.name} (predefined)`
382
+ : group.kind === 'everyone'
383
+ ? `${group.name} (everyone in no other group)`
384
+ : group.name,
381
385
  [
382
386
  (_a = group.description) !== null && _a !== void 0 ? _a : 'no description',
383
- `members: ${group.members.length === 0 ? 'none' : group.members.map((member) => { var _a; return (_a = member.email) !== null && _a !== void 0 ? _a : member.userId; }).join(', ')}`,
387
+ group.kind === 'everyone'
388
+ ? 'members: everyone on the team in no other group'
389
+ : `members: ${group.members.length === 0 ? 'none' : group.members.map((member) => { var _a; return (_a = member.email) !== null && _a !== void 0 ? _a : member.userId; }).join(', ')}`,
384
390
  `products: ${group.products.length === 0 ? 'none (no narrowing)' : group.products.map((product) => product.slug).join(', ')}`,
385
391
  ],
386
392
  ];
@@ -1 +1 @@
1
- {"version":3,"file":"teams-lifecycle.js","sourceRoot":"","sources":["../../src/commands/teams-lifecycle.ts"],"names":[],"mappings":"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","sourcesContent":["import { requireSession, resolveAuthEnvironment } from '../auth/session';\nimport type { CliContext } from '../context';\nimport { invalidStateError, usageError } from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport { cli } from '../invocation';\nimport { resolveSourceTarget } from '../source-target';\nimport {\n type TeamGroup,\n type TeamHealthRow,\n createTeamGroup,\n deleteTeamGroup,\n leaveTeam,\n listTeamGroups,\n listTeamHealth,\n listTeamWorkspaces,\n ownTeamHealth,\n resendTeamInvitation,\n runTeamHealthCheck,\n setTeamDefaultWorkspace,\n setTeamGroupMember,\n updateTeamGroup,\n} from '../team-lifecycle-api';\nimport type { ResultRow } from '../ui';\nimport { promptYesNo } from './publish';\nimport { TeamsClient, type TeamsArgs, canPrompt } from './teams';\n\n/**\n * A team's lifecycle from the terminal, for the Source admin:\n * `teams members resend`, `teams leave`, `teams groups …`, `teams health`\n * and `teams workspace …`. Each is parsed before a session is touched\n * (`parseLifecycle`), and a change that takes something away is confirmed\n * first — asked at a terminal, `--yes` in a script or agent run — so a usage\n * error or an unconfirmed change never costs a request. The host does the\n * rest through the services the app's own screens use, with an Admin Audit\n * row per write.\n *\n * Ownership transfer and team deletion are not here: in the app they are\n * the primary owner's alone, confirmed by a code emailed to them.\n */\n\nexport const LIFECYCLE_SUBCOMMANDS = [\n 'leave',\n 'groups',\n 'health',\n 'workspace',\n] as const;\ntype LifecycleSubcommand = (typeof LIFECYCLE_SUBCOMMANDS)[number];\n\n/** `teams members <verb>` verbs handled here rather than in onboarding. */\nexport const LIFECYCLE_MEMBER_VERBS = ['resend'] as const;\n\n/** What an unconfirmed change says, and the question a terminal is asked. */\nexport interface Confirmation {\n what: string;\n command: string;\n question: string;\n}\n\nexport type LifecyclePlan = (\n | { kind: 'resend'; team: string; email: string }\n | { kind: 'leave'; team: string }\n | { kind: 'groups-list'; team: string }\n | {\n kind: 'groups-create';\n team: string;\n name: string;\n description?: string;\n products?: string[];\n }\n | {\n kind: 'groups-update';\n team: string;\n group: string;\n name?: string;\n description?: string | null;\n products?: string[];\n }\n | { kind: 'groups-delete'; team: string; group: string }\n | {\n kind: 'groups-member';\n team: string;\n group: string;\n email: string;\n member: boolean;\n }\n | {\n kind: 'health';\n team: string;\n product?: string;\n run: boolean;\n /** `--mine`: the caller's own personal connection to <product>. */\n mine?: boolean;\n }\n | { kind: 'workspace-list'; team: string }\n | { kind: 'workspace-default'; team: string; workspace: string }\n) & { confirm?: Confirmation };\n\nexport function isLifecycleSubcommand(\n value: string | undefined,\n): value is LifecycleSubcommand {\n return (LIFECYCLE_SUBCOMMANDS as readonly string[]).includes(value ?? '');\n}\n\nexport function isLifecycleMemberVerb(value: string | undefined): boolean {\n return (LIFECYCLE_MEMBER_VERBS as readonly string[]).includes(value ?? '');\n}\n\nconst GROUPS_USAGE =\n 'Run one of: ekanos teams groups list <team>, ekanos teams groups create <team> <name> [--description <text>] [--products <slug,slug>], ekanos teams groups update <team> <group> [--name <name>] [--description <text>] [--products <slug,slug>|none], ekanos teams groups delete <team> <group> --yes, ekanos teams groups members add|remove <team> <group> <email>.';\nconst WORKSPACE_USAGE =\n 'Run \"ekanos teams workspace list <team>\" or \"ekanos teams workspace default <team> <workspace>\".';\n\n/**\n * `subcommand` is `members` (with `resend` first in `rest`) or one\n * of {@link LIFECYCLE_SUBCOMMANDS}.\n */\nexport function parseLifecycle(\n subcommand: string,\n rest: readonly string[],\n args: Pick<TeamsArgs, 'yes' | 'flags'>,\n): LifecyclePlan {\n const flags = args.flags ?? {};\n\n if (subcommand === 'members') {\n const [, team, email, ...extra] = rest;\n noExtra(extra);\n return {\n kind: 'resend',\n team: slugOf(team, 'team'),\n email: emailOf(email),\n };\n }\n\n if (subcommand === 'leave') {\n const [team, ...extra] = rest;\n noExtra(extra);\n const teamSlug = slugOf(team, 'team');\n return {\n kind: 'leave',\n team: teamSlug,\n ...confirmUnless(args.yes, {\n what: `Leaving ${teamSlug} ends your own membership of it; only an invitation brings you back.`,\n command: `${cli()} teams leave ${teamSlug} --yes`,\n question: `Leave ${teamSlug}? [y/N]`,\n }),\n };\n }\n\n if (subcommand === 'health') {\n const [team, product, ...extra] = rest;\n noExtra(extra);\n const run = flags.run === true;\n const productSlug =\n product === undefined ? undefined : slugOf(product, 'product');\n if (run && !productSlug) {\n throw usageError(\n 'teams health --run checks one integration; name it.',\n 'Run \"ekanos teams health <team> <product> --run\"; \"ekanos teams health <team>\" lists them.',\n );\n }\n const mine = flags.mine === true;\n if (mine && !productSlug) {\n throw usageError(\n 'teams health --mine shows your own connection to one integration; name it.',\n 'Run \"ekanos teams health <team> <product> --mine [--run]\".',\n );\n }\n return {\n kind: 'health',\n team: slugOf(team, 'team'),\n ...(productSlug ? { product: productSlug } : {}),\n run,\n ...(mine ? { mine } : {}),\n };\n }\n\n if (subcommand === 'workspace') {\n const [verb, team, workspace, ...extra] = rest;\n noExtra(extra);\n if (verb === 'list') {\n if (workspace !== undefined) noExtra([workspace]);\n return { kind: 'workspace-list', team: slugOf(team, 'team') };\n }\n if (verb === 'default') {\n const teamSlug = slugOf(team, 'team');\n if (!workspace?.trim()) {\n throw usageError(\n 'Name the workspace.',\n `Run \"${cli()} teams workspace default ${teamSlug} <workspace>\"; \"${cli()} teams workspace list ${teamSlug}\" lists them.`,\n );\n }\n return {\n kind: 'workspace-default',\n team: teamSlug,\n workspace: workspace.trim().toLowerCase(),\n };\n }\n throw usageError(\n verb\n ? `Unknown teams workspace subcommand \"${verb}\".`\n : 'teams workspace needs a subcommand.',\n WORKSPACE_USAGE,\n );\n }\n\n const [verb, ...operands] = rest;\n if (verb === 'list') {\n const [team, ...extra] = operands;\n noExtra(extra);\n return { kind: 'groups-list', team: slugOf(team, 'team') };\n }\n if (verb === 'create') {\n const [team, name, ...extra] = operands;\n noExtra(extra);\n const teamSlug = slugOf(team, 'team');\n if (!name?.trim()) {\n throw usageError(\n 'Name the group.',\n `Run \"${cli()} teams groups create ${teamSlug} \\\\\"Loan officers\\\\\"\".`,\n );\n }\n const description = stringFlag(flags.description);\n const products = productsFlag(flags.products);\n return {\n kind: 'groups-create',\n team: teamSlug,\n name: name.trim(),\n ...(description === undefined ? {} : { description }),\n ...(products === undefined ? {} : { products }),\n };\n }\n if (verb === 'update') {\n const [team, group, ...extra] = operands;\n noExtra(extra);\n const teamSlug = slugOf(team, 'team');\n const groupRef = groupOf(group, teamSlug);\n const name = stringFlag(flags.name);\n const description = stringFlag(flags.description);\n const products = productsFlag(flags.products);\n if (\n name === undefined &&\n description === undefined &&\n products === undefined\n ) {\n throw usageError(\n 'Nothing to change.',\n `Pass --name, --description or --products, e.g. \"${cli()} teams groups update ${teamSlug} ${quote(groupRef)} --products linear,zendesk\".`,\n );\n }\n return {\n kind: 'groups-update',\n team: teamSlug,\n group: groupRef,\n ...(name === undefined ? {} : { name }),\n ...(description === undefined\n ? {}\n : { description: description === '' ? null : description }),\n ...(products === undefined ? {} : { products }),\n };\n }\n if (verb === 'delete') {\n const [team, group, ...extra] = operands;\n noExtra(extra);\n const teamSlug = slugOf(team, 'team');\n const groupRef = groupOf(group, teamSlug);\n return {\n kind: 'groups-delete',\n team: teamSlug,\n group: groupRef,\n ...confirmUnless(args.yes, {\n what: `Deleting the group ${groupRef} of ${teamSlug} takes away what it narrows: its members see what the team's other groups (or the whole team) give them.`,\n command: `${cli()} teams groups delete ${teamSlug} ${quote(groupRef)} --yes`,\n question: `Delete the group ${groupRef} of ${teamSlug}? [y/N]`,\n }),\n };\n }\n if (verb === 'members') {\n const [action, team, group, email, ...extra] = operands;\n noExtra(extra);\n if (action !== 'add' && action !== 'remove') {\n throw usageError(\n action\n ? `Unknown teams groups members subcommand \"${action}\".`\n : 'teams groups members needs add or remove.',\n GROUPS_USAGE,\n );\n }\n const teamSlug = slugOf(team, 'team');\n const groupRef = groupOf(group, teamSlug);\n const address = emailOf(email);\n return {\n kind: 'groups-member',\n team: teamSlug,\n group: groupRef,\n email: address,\n member: action === 'add',\n ...(action === 'remove'\n ? confirmUnless(args.yes, {\n what: `Taking ${address} out of ${groupRef} changes what they see on ${teamSlug}.`,\n command: `${cli()} teams groups members remove ${teamSlug} ${quote(groupRef)} ${address} --yes`,\n question: `Take ${address} out of ${groupRef} on ${teamSlug}? [y/N]`,\n })\n : {}),\n };\n }\n throw usageError(\n verb\n ? `Unknown teams groups subcommand \"${verb}\".`\n : 'teams groups needs a subcommand.',\n GROUPS_USAGE,\n );\n}\n\nexport async function runLifecycle(\n ctx: CliContext,\n args: TeamsArgs,\n plan: LifecyclePlan,\n): Promise<ExitCode> {\n if (plan.confirm) await confirmChange(ctx, args, plan.confirm);\n\n const env = resolveAuthEnvironment(ctx, args.host, args.env, {\n projectDir: args.dir,\n });\n const resolved = await resolveSourceTarget(env, requireSession(env), args);\n const client = new TeamsClient(env, resolved.session);\n const host = env.host;\n const source = resolved.source;\n const team = { source, team: plan.team };\n\n switch (plan.kind) {\n case 'resend': {\n const done = await client.call((token) =>\n resendTeamInvitation(host, token, { ...team, email: plan.email }),\n );\n return ctx.succeed(\n { host, ...done },\n ctx.ui.result({\n title:\n done.action === 'resent'\n ? `Resent ${done.email}'s invitation to ${done.team.slug}`\n : `Renewed ${done.email}'s expired invitation to ${done.team.slug}`,\n rows: [\n ['Role', done.role],\n ['Expires', done.expiresAt.slice(0, 10)],\n ],\n notes: [\n done.action === 'resent'\n ? 'A fresh invitation email is on its way; the earlier link stops working.'\n : 'The link they already have works again; no new email is sent for a renewal.',\n ],\n }),\n );\n }\n\n case 'leave': {\n const done = await client.call((token) => leaveTeam(host, token, team));\n return ctx.succeed(\n { host, ...done },\n ctx.ui.result({\n title: `You left ${done.team.slug}`,\n rows: [['Your role was', done.role]],\n notes: [\n `As the Source admin you still manage it from here (\"${cli()} teams show ${done.team.slug}\").`,\n ],\n }),\n );\n }\n\n case 'groups-list': {\n const list = await client.call((token) =>\n listTeamGroups(host, token, team),\n );\n return ctx.succeed(\n { host, ...list },\n ctx.ui.result({\n title:\n list.groups.length === 0\n ? `${list.team.slug} has no groups`\n : `Groups of ${list.team.slug}`,\n tone: list.groups.length === 0 ? 'warn' : 'ok',\n rows: list.groups.map(groupRow),\n notes: [\n `A group narrows what its members see to its products. \"${cli()} teams groups create ${list.team.slug} <name> --products <slug,slug>\" adds one.`,\n ],\n }),\n );\n }\n\n case 'groups-create': {\n const done = await client.call((token) =>\n createTeamGroup(host, token, team, {\n name: plan.name,\n ...(plan.description === undefined\n ? {}\n : { description: plan.description }),\n ...(plan.products === undefined ? {} : { products: plan.products }),\n }),\n );\n return ctx.succeed(\n { host, ...done },\n ctx.ui.result({\n title: `Created group ${done.group.name} on ${done.team.slug}`,\n rows: [groupRow(done.group)],\n notes: [\n `Add members with \"${cli()} teams groups members add ${done.team.slug} ${quote(done.group.name)} <email>\".`,\n ],\n }),\n );\n }\n\n case 'groups-update': {\n const done = await client.call((token) =>\n updateTeamGroup(\n host,\n token,\n { ...team, group: plan.group },\n {\n ...(plan.name === undefined ? {} : { name: plan.name }),\n ...(plan.description === undefined\n ? {}\n : { description: plan.description }),\n ...(plan.products === undefined ? {} : { products: plan.products }),\n },\n ),\n );\n return ctx.succeed(\n { host, ...done },\n ctx.ui.result({\n title: `Updated group ${done.group.name} on ${done.team.slug}`,\n rows: [groupRow(done.group)],\n }),\n );\n }\n\n case 'groups-delete': {\n const done = await client.call((token) =>\n deleteTeamGroup(host, token, { ...team, group: plan.group }),\n );\n return ctx.succeed(\n { host, ...done },\n ctx.ui.result({\n title: `Deleted group ${done.group.name} from ${done.team.slug}`,\n tone: 'warn',\n }),\n );\n }\n\n case 'groups-member': {\n const done = await client.call((token) =>\n setTeamGroupMember(\n host,\n token,\n { ...team, group: plan.group, email: plan.email },\n plan.member,\n ),\n );\n return ctx.succeed(\n { host, ...done },\n ctx.ui.result({\n title: !done.changed\n ? `${done.email} was already ${plan.member ? 'in' : 'not in'} ${done.group.name}`\n : plan.member\n ? `Added ${done.email} to ${done.group.name}`\n : `Took ${done.email} out of ${done.group.name}`,\n rows: [groupRow(done.group)],\n }),\n );\n }\n\n case 'health': {\n if (plan.mine && plan.product) {\n const product = plan.product;\n const done = await client.call((token) =>\n ownTeamHealth(host, token, { ...team, product }, plan.run),\n );\n return ctx.succeed(\n { host, ...done, mine: true },\n ctx.ui.result({\n title: `Your ${done.integration.productName} connection: ${done.integration.status}`,\n tone: toneOf(done.integration),\n rows: healthRows(done.integration),\n notes: plan.run\n ? []\n : [\n `\"${cli()} teams health ${done.team.slug} ${product} --mine --run\" checks it now.`,\n ],\n }),\n );\n }\n if (plan.run && plan.product) {\n const product = plan.product;\n const done = await client.call((token) =>\n runTeamHealthCheck(host, token, { ...team, product }),\n );\n return ctx.succeed(\n { host, ...done },\n ctx.ui.result({\n title: `${done.integration.productName} on ${done.team.slug}: ${done.integration.status}`,\n tone: toneOf(done.integration),\n rows: healthRows(done.integration),\n }),\n );\n }\n const list = await client.call((token) =>\n listTeamHealth(host, token, team),\n );\n const rows = plan.product\n ? list.integrations.filter((row) => row.slug === plan.product)\n : list.integrations;\n if (plan.product && rows.length === 0) {\n throw invalidStateError(\n `${list.team.slug} has not connected ${plan.product}, so it has no health to show.`,\n `\"${cli()} teams health ${list.team.slug}\" lists what it has connected.`,\n );\n }\n const data = { host, ...list, integrations: rows };\n if (plan.product) {\n const row = rows[0]!;\n return ctx.succeed(\n data,\n ctx.ui.result({\n title: `${row.productName} on ${list.team.slug}: ${row.status}`,\n tone: toneOf(row),\n rows: healthRows(row),\n notes: [\n `\"${cli()} teams health ${list.team.slug} ${row.slug} --run\" checks it now.`,\n ],\n }),\n );\n }\n return ctx.succeed(\n data,\n ctx.ui.result({\n title:\n rows.length === 0\n ? `${list.team.slug} has no connected integrations`\n : `Integration health on ${list.team.slug}`,\n tone:\n rows.length === 0\n ? 'warn'\n : rows.some((row) => row.status === 'unhealthy')\n ? 'err'\n : rows.some((row) => row.status !== 'healthy')\n ? 'warn'\n : 'ok',\n rows: rows.map((row): ResultRow => [\n row.slug,\n `${row.status}${row.statusReason ? ` · ${row.statusReason}` : ''}${row.lastCheckedAt ? ` · checked ${row.lastCheckedAt.slice(0, 10)}` : ' · never checked'}`,\n ]),\n notes:\n rows.length === 0\n ? []\n : [\n `\"${cli()} teams health ${list.team.slug} <product> --run\" checks one now.`,\n ],\n }),\n );\n }\n\n case 'workspace-list': {\n const list = await client.call((token) =>\n listTeamWorkspaces(host, token, team),\n );\n return ctx.succeed(\n { host, ...list },\n ctx.ui.result({\n title:\n list.workspaces.length === 0\n ? `${list.team.slug} has no workspaces`\n : `Workspaces of ${list.team.slug}`,\n tone: list.workspaces.length === 0 ? 'warn' : 'ok',\n rows: list.workspaces.map((workspace): ResultRow => [\n workspace.slug,\n [\n workspace.label ?? workspace.name,\n ...(workspace.isDefault ? ['default'] : []),\n ...(workspace.visible ? [] : ['hidden by the team']),\n ].join(' · '),\n ]),\n notes: [\n `\"${cli()} teams workspace default ${list.team.slug} <workspace>\" sets the one the team lands on.`,\n ],\n }),\n );\n }\n\n case 'workspace-default': {\n const done = await client.call((token) =>\n setTeamDefaultWorkspace(host, token, team, plan.workspace),\n );\n return ctx.succeed(\n { host, ...done },\n ctx.ui.result({\n title: done.changed\n ? `${done.team.slug} now lands on ${done.workspace.label ?? done.workspace.name}`\n : `${done.workspace.label ?? done.workspace.name} is already ${done.team.slug}'s default`,\n rows: [['Was', done.previous?.slug ?? '—']],\n notes: ['A member who picked their own default keeps theirs.'],\n }),\n );\n }\n }\n}\n\nfunction confirmUnless(\n yes: boolean,\n confirm: Confirmation,\n): { confirm?: Confirmation } {\n return yes ? {} : { confirm };\n}\n\n/**\n * A change that takes something away: asked at a terminal; a script, an\n * agent run or `--json` passes `--yes` instead. Asked before any request.\n */\nexport async function confirmChange(\n ctx: CliContext,\n args: TeamsArgs,\n confirm: Confirmation,\n): Promise<void> {\n if (!canPrompt(ctx, args)) {\n throw invalidStateError(\n confirm.what,\n `Re-run with --yes: ${confirm.command}`,\n );\n }\n const { ask } = args;\n const confirmed = ask\n ? /^y(es)?$/i.test((await ask(confirm.question)).trim())\n : await promptYesNo(confirm.question);\n if (!confirmed) {\n throw invalidStateError(\n `Not confirmed: ${confirm.what}`,\n 'Nothing was changed.',\n );\n }\n}\n\nfunction groupRow(group: TeamGroup): ResultRow {\n return [\n group.name,\n [\n group.description ?? 'no description',\n `members: ${group.members.length === 0 ? 'none' : group.members.map((member) => member.email ?? member.userId).join(', ')}`,\n `products: ${group.products.length === 0 ? 'none (no narrowing)' : group.products.map((product) => product.slug).join(', ')}`,\n ],\n ];\n}\n\nfunction healthRows(row: TeamHealthRow): ResultRow[] {\n return [\n ['Status', row.status],\n ...(row.statusReason ? [['Why', row.statusReason] as const] : []),\n ['Last checked', row.lastCheckedAt ?? 'never'],\n ['Last success', row.lastSuccessAt ?? '—'],\n ['Last failure', row.lastFailureAt ?? '—'],\n ...(row.lastErrorMessage\n ? [['Last error', row.lastErrorMessage] as const]\n : []),\n ...(row.tokenExpiresAt\n ? [['Token expires', row.tokenExpiresAt] as const]\n : []),\n ];\n}\n\nfunction toneOf(row: TeamHealthRow) {\n return row.status === 'healthy'\n ? ('ok' as const)\n : row.status === 'unhealthy'\n ? ('err' as const)\n : ('warn' as const);\n}\n\nfunction stringFlag(value: unknown): string | undefined {\n return typeof value === 'string' ? value.trim() : undefined;\n}\n\n/** `--products a,b`: the list; `--products none` (or empty): no products. */\nfunction productsFlag(value: unknown): string[] | undefined {\n if (typeof value !== 'string') return undefined;\n const trimmed = value.trim().toLowerCase();\n if (trimmed === '' || trimmed === 'none') return [];\n return [\n ...new Set(\n trimmed\n .split(',')\n .map((slug) => slug.trim())\n .filter(Boolean)\n .map((slug) => slugOf(slug, 'product')),\n ),\n ];\n}\n\nfunction groupOf(value: string | undefined, team: string): string {\n const group = value?.trim();\n if (group) return group;\n throw usageError(\n 'Name the group, by name or id.',\n `\"${cli()} teams groups list ${team}\" lists them.`,\n );\n}\n\nfunction quote(value: string): string {\n return /^[A-Za-z0-9._-]+$/.test(value) ? value : `\"${value}\"`;\n}\n\nfunction noExtra(extra: readonly string[]) {\n if (extra.length > 0) {\n throw usageError(\n `Unexpected argument \"${extra[0]}\".`,\n 'See \"ekanos teams --help\".',\n );\n }\n}\n\nfunction slugOf(value: string | undefined, what: 'team' | 'product'): string {\n const slug = value?.trim().toLowerCase();\n if (slug && /^[a-z0-9][a-z0-9-]*$/.test(slug)) return slug;\n throw usageError(\n value ? `\"${value}\" is not a ${what} slug.` : `Name the ${what}.`,\n what === 'team'\n ? '\"ekanos teams list\" lists the teams, e.g. \"ekanos teams health bank-a\".'\n : '\"ekanos catalog\" lists the products, e.g. \"ekanos teams health bank-a zendesk\".',\n );\n}\n\nfunction emailOf(value: string | undefined): string {\n const email = value?.trim().toLowerCase();\n if (email && /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email)) return email;\n throw usageError(\n value ? `\"${value}\" is not an email address.` : 'Name the person by email.',\n 'e.g. \"ekanos teams members resend bank-a ana@bank-a.com\".',\n );\n}\n"]}
1
+ {"version":3,"file":"teams-lifecycle.js","sourceRoot":"","sources":["../../src/commands/teams-lifecycle.ts"],"names":[],"mappings":"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","sourcesContent":["import { requireSession, resolveAuthEnvironment } from '../auth/session';\nimport type { CliContext } from '../context';\nimport { invalidStateError, usageError } from '../errors';\nimport type { ExitCode } from '../exit-codes';\nimport { cli } from '../invocation';\nimport { resolveSourceTarget } from '../source-target';\nimport {\n type TeamGroup,\n type TeamHealthRow,\n createTeamGroup,\n deleteTeamGroup,\n leaveTeam,\n listTeamGroups,\n listTeamHealth,\n listTeamWorkspaces,\n ownTeamHealth,\n resendTeamInvitation,\n runTeamHealthCheck,\n setTeamDefaultWorkspace,\n setTeamGroupMember,\n updateTeamGroup,\n} from '../team-lifecycle-api';\nimport type { ResultRow } from '../ui';\nimport { promptYesNo } from './publish';\nimport { TeamsClient, type TeamsArgs, canPrompt } from './teams';\n\n/**\n * A team's lifecycle from the terminal, for the Source admin:\n * `teams members resend`, `teams leave`, `teams groups …`, `teams health`\n * and `teams workspace …`. Each is parsed before a session is touched\n * (`parseLifecycle`), and a change that takes something away is confirmed\n * first — asked at a terminal, `--yes` in a script or agent run — so a usage\n * error or an unconfirmed change never costs a request. The host does the\n * rest through the services the app's own screens use, with an Admin Audit\n * row per write.\n *\n * Ownership transfer and team deletion are not here: in the app they are\n * the primary owner's alone, confirmed by a code emailed to them.\n */\n\nexport const LIFECYCLE_SUBCOMMANDS = [\n 'leave',\n 'groups',\n 'health',\n 'workspace',\n] as const;\ntype LifecycleSubcommand = (typeof LIFECYCLE_SUBCOMMANDS)[number];\n\n/** `teams members <verb>` verbs handled here rather than in onboarding. */\nexport const LIFECYCLE_MEMBER_VERBS = ['resend'] as const;\n\n/** What an unconfirmed change says, and the question a terminal is asked. */\nexport interface Confirmation {\n what: string;\n command: string;\n question: string;\n}\n\nexport type LifecyclePlan = (\n | { kind: 'resend'; team: string; email: string }\n | { kind: 'leave'; team: string }\n | { kind: 'groups-list'; team: string }\n | {\n kind: 'groups-create';\n team: string;\n name: string;\n description?: string;\n products?: string[];\n }\n | {\n kind: 'groups-update';\n team: string;\n group: string;\n name?: string;\n description?: string | null;\n products?: string[];\n }\n | { kind: 'groups-delete'; team: string; group: string }\n | {\n kind: 'groups-member';\n team: string;\n group: string;\n email: string;\n member: boolean;\n }\n | {\n kind: 'health';\n team: string;\n product?: string;\n run: boolean;\n /** `--mine`: the caller's own personal connection to <product>. */\n mine?: boolean;\n }\n | { kind: 'workspace-list'; team: string }\n | { kind: 'workspace-default'; team: string; workspace: string }\n) & { confirm?: Confirmation };\n\nexport function isLifecycleSubcommand(\n value: string | undefined,\n): value is LifecycleSubcommand {\n return (LIFECYCLE_SUBCOMMANDS as readonly string[]).includes(value ?? '');\n}\n\nexport function isLifecycleMemberVerb(value: string | undefined): boolean {\n return (LIFECYCLE_MEMBER_VERBS as readonly string[]).includes(value ?? '');\n}\n\nconst GROUPS_USAGE =\n 'Run one of: ekanos teams groups list <team>, ekanos teams groups create <team> <name> [--description <text>] [--products <slug,slug>], ekanos teams groups update <team> <group> [--name <name>] [--description <text>] [--products <slug,slug>|none], ekanos teams groups delete <team> <group> --yes, ekanos teams groups members add|remove <team> <group> <email>.';\nconst WORKSPACE_USAGE =\n 'Run \"ekanos teams workspace list <team>\" or \"ekanos teams workspace default <team> <workspace>\".';\n\n/**\n * `subcommand` is `members` (with `resend` first in `rest`) or one\n * of {@link LIFECYCLE_SUBCOMMANDS}.\n */\nexport function parseLifecycle(\n subcommand: string,\n rest: readonly string[],\n args: Pick<TeamsArgs, 'yes' | 'flags'>,\n): LifecyclePlan {\n const flags = args.flags ?? {};\n\n if (subcommand === 'members') {\n const [, team, email, ...extra] = rest;\n noExtra(extra);\n return {\n kind: 'resend',\n team: slugOf(team, 'team'),\n email: emailOf(email),\n };\n }\n\n if (subcommand === 'leave') {\n const [team, ...extra] = rest;\n noExtra(extra);\n const teamSlug = slugOf(team, 'team');\n return {\n kind: 'leave',\n team: teamSlug,\n ...confirmUnless(args.yes, {\n what: `Leaving ${teamSlug} ends your own membership of it; only an invitation brings you back.`,\n command: `${cli()} teams leave ${teamSlug} --yes`,\n question: `Leave ${teamSlug}? [y/N]`,\n }),\n };\n }\n\n if (subcommand === 'health') {\n const [team, product, ...extra] = rest;\n noExtra(extra);\n const run = flags.run === true;\n const productSlug =\n product === undefined ? undefined : slugOf(product, 'product');\n if (run && !productSlug) {\n throw usageError(\n 'teams health --run checks one integration; name it.',\n 'Run \"ekanos teams health <team> <product> --run\"; \"ekanos teams health <team>\" lists them.',\n );\n }\n const mine = flags.mine === true;\n if (mine && !productSlug) {\n throw usageError(\n 'teams health --mine shows your own connection to one integration; name it.',\n 'Run \"ekanos teams health <team> <product> --mine [--run]\".',\n );\n }\n return {\n kind: 'health',\n team: slugOf(team, 'team'),\n ...(productSlug ? { product: productSlug } : {}),\n run,\n ...(mine ? { mine } : {}),\n };\n }\n\n if (subcommand === 'workspace') {\n const [verb, team, workspace, ...extra] = rest;\n noExtra(extra);\n if (verb === 'list') {\n if (workspace !== undefined) noExtra([workspace]);\n return { kind: 'workspace-list', team: slugOf(team, 'team') };\n }\n if (verb === 'default') {\n const teamSlug = slugOf(team, 'team');\n if (!workspace?.trim()) {\n throw usageError(\n 'Name the workspace.',\n `Run \"${cli()} teams workspace default ${teamSlug} <workspace>\"; \"${cli()} teams workspace list ${teamSlug}\" lists them.`,\n );\n }\n return {\n kind: 'workspace-default',\n team: teamSlug,\n workspace: workspace.trim().toLowerCase(),\n };\n }\n throw usageError(\n verb\n ? `Unknown teams workspace subcommand \"${verb}\".`\n : 'teams workspace needs a subcommand.',\n WORKSPACE_USAGE,\n );\n }\n\n const [verb, ...operands] = rest;\n if (verb === 'list') {\n const [team, ...extra] = operands;\n noExtra(extra);\n return { kind: 'groups-list', team: slugOf(team, 'team') };\n }\n if (verb === 'create') {\n const [team, name, ...extra] = operands;\n noExtra(extra);\n const teamSlug = slugOf(team, 'team');\n if (!name?.trim()) {\n throw usageError(\n 'Name the group.',\n `Run \"${cli()} teams groups create ${teamSlug} \\\\\"Loan officers\\\\\"\".`,\n );\n }\n const description = stringFlag(flags.description);\n const products = productsFlag(flags.products);\n return {\n kind: 'groups-create',\n team: teamSlug,\n name: name.trim(),\n ...(description === undefined ? {} : { description }),\n ...(products === undefined ? {} : { products }),\n };\n }\n if (verb === 'update') {\n const [team, group, ...extra] = operands;\n noExtra(extra);\n const teamSlug = slugOf(team, 'team');\n const groupRef = groupOf(group, teamSlug);\n const name = stringFlag(flags.name);\n const description = stringFlag(flags.description);\n const products = productsFlag(flags.products);\n if (\n name === undefined &&\n description === undefined &&\n products === undefined\n ) {\n throw usageError(\n 'Nothing to change.',\n `Pass --name, --description or --products, e.g. \"${cli()} teams groups update ${teamSlug} ${quote(groupRef)} --products linear,zendesk\".`,\n );\n }\n return {\n kind: 'groups-update',\n team: teamSlug,\n group: groupRef,\n ...(name === undefined ? {} : { name }),\n ...(description === undefined\n ? {}\n : { description: description === '' ? null : description }),\n ...(products === undefined ? {} : { products }),\n };\n }\n if (verb === 'delete') {\n const [team, group, ...extra] = operands;\n noExtra(extra);\n const teamSlug = slugOf(team, 'team');\n const groupRef = groupOf(group, teamSlug);\n return {\n kind: 'groups-delete',\n team: teamSlug,\n group: groupRef,\n ...confirmUnless(args.yes, {\n what: `Deleting the group ${groupRef} of ${teamSlug} takes away what it narrows: its members see what the team's other groups (or the whole team) give them.`,\n command: `${cli()} teams groups delete ${teamSlug} ${quote(groupRef)} --yes`,\n question: `Delete the group ${groupRef} of ${teamSlug}? [y/N]`,\n }),\n };\n }\n if (verb === 'members') {\n const [action, team, group, email, ...extra] = operands;\n noExtra(extra);\n if (action !== 'add' && action !== 'remove') {\n throw usageError(\n action\n ? `Unknown teams groups members subcommand \"${action}\".`\n : 'teams groups members needs add or remove.',\n GROUPS_USAGE,\n );\n }\n const teamSlug = slugOf(team, 'team');\n const groupRef = groupOf(group, teamSlug);\n const address = emailOf(email);\n return {\n kind: 'groups-member',\n team: teamSlug,\n group: groupRef,\n email: address,\n member: action === 'add',\n ...(action === 'remove'\n ? confirmUnless(args.yes, {\n what: `Taking ${address} out of ${groupRef} changes what they see on ${teamSlug}.`,\n command: `${cli()} teams groups members remove ${teamSlug} ${quote(groupRef)} ${address} --yes`,\n question: `Take ${address} out of ${groupRef} on ${teamSlug}? [y/N]`,\n })\n : {}),\n };\n }\n throw usageError(\n verb\n ? `Unknown teams groups subcommand \"${verb}\".`\n : 'teams groups needs a subcommand.',\n GROUPS_USAGE,\n );\n}\n\nexport async function runLifecycle(\n ctx: CliContext,\n args: TeamsArgs,\n plan: LifecyclePlan,\n): Promise<ExitCode> {\n if (plan.confirm) await confirmChange(ctx, args, plan.confirm);\n\n const env = resolveAuthEnvironment(ctx, args.host, args.env, {\n projectDir: args.dir,\n });\n const resolved = await resolveSourceTarget(env, requireSession(env), args);\n const client = new TeamsClient(env, resolved.session);\n const host = env.host;\n const source = resolved.source;\n const team = { source, team: plan.team };\n\n switch (plan.kind) {\n case 'resend': {\n const done = await client.call((token) =>\n resendTeamInvitation(host, token, { ...team, email: plan.email }),\n );\n return ctx.succeed(\n { host, ...done },\n ctx.ui.result({\n title:\n done.action === 'resent'\n ? `Resent ${done.email}'s invitation to ${done.team.slug}`\n : `Renewed ${done.email}'s expired invitation to ${done.team.slug}`,\n rows: [\n ['Role', done.role],\n ['Expires', done.expiresAt.slice(0, 10)],\n ],\n notes: [\n done.action === 'resent'\n ? 'A fresh invitation email is on its way; the earlier link stops working.'\n : 'The link they already have works again; no new email is sent for a renewal.',\n ],\n }),\n );\n }\n\n case 'leave': {\n const done = await client.call((token) => leaveTeam(host, token, team));\n return ctx.succeed(\n { host, ...done },\n ctx.ui.result({\n title: `You left ${done.team.slug}`,\n rows: [['Your role was', done.role]],\n notes: [\n `As the Source admin you still manage it from here (\"${cli()} teams show ${done.team.slug}\").`,\n ],\n }),\n );\n }\n\n case 'groups-list': {\n const list = await client.call((token) =>\n listTeamGroups(host, token, team),\n );\n return ctx.succeed(\n { host, ...list },\n ctx.ui.result({\n title:\n list.groups.length === 0\n ? `${list.team.slug} has no groups`\n : `Groups of ${list.team.slug}`,\n tone: list.groups.length === 0 ? 'warn' : 'ok',\n rows: list.groups.map(groupRow),\n notes: [\n `A group narrows what its members see to its products. \"${cli()} teams groups create ${list.team.slug} <name> --products <slug,slug>\" adds one.`,\n ],\n }),\n );\n }\n\n case 'groups-create': {\n const done = await client.call((token) =>\n createTeamGroup(host, token, team, {\n name: plan.name,\n ...(plan.description === undefined\n ? {}\n : { description: plan.description }),\n ...(plan.products === undefined ? {} : { products: plan.products }),\n }),\n );\n return ctx.succeed(\n { host, ...done },\n ctx.ui.result({\n title: `Created group ${done.group.name} on ${done.team.slug}`,\n rows: [groupRow(done.group)],\n notes: [\n `Add members with \"${cli()} teams groups members add ${done.team.slug} ${quote(done.group.name)} <email>\".`,\n ],\n }),\n );\n }\n\n case 'groups-update': {\n const done = await client.call((token) =>\n updateTeamGroup(\n host,\n token,\n { ...team, group: plan.group },\n {\n ...(plan.name === undefined ? {} : { name: plan.name }),\n ...(plan.description === undefined\n ? {}\n : { description: plan.description }),\n ...(plan.products === undefined ? {} : { products: plan.products }),\n },\n ),\n );\n return ctx.succeed(\n { host, ...done },\n ctx.ui.result({\n title: `Updated group ${done.group.name} on ${done.team.slug}`,\n rows: [groupRow(done.group)],\n }),\n );\n }\n\n case 'groups-delete': {\n const done = await client.call((token) =>\n deleteTeamGroup(host, token, { ...team, group: plan.group }),\n );\n return ctx.succeed(\n { host, ...done },\n ctx.ui.result({\n title: `Deleted group ${done.group.name} from ${done.team.slug}`,\n tone: 'warn',\n }),\n );\n }\n\n case 'groups-member': {\n const done = await client.call((token) =>\n setTeamGroupMember(\n host,\n token,\n { ...team, group: plan.group, email: plan.email },\n plan.member,\n ),\n );\n return ctx.succeed(\n { host, ...done },\n ctx.ui.result({\n title: !done.changed\n ? `${done.email} was already ${plan.member ? 'in' : 'not in'} ${done.group.name}`\n : plan.member\n ? `Added ${done.email} to ${done.group.name}`\n : `Took ${done.email} out of ${done.group.name}`,\n rows: [groupRow(done.group)],\n }),\n );\n }\n\n case 'health': {\n if (plan.mine && plan.product) {\n const product = plan.product;\n const done = await client.call((token) =>\n ownTeamHealth(host, token, { ...team, product }, plan.run),\n );\n return ctx.succeed(\n { host, ...done, mine: true },\n ctx.ui.result({\n title: `Your ${done.integration.productName} connection: ${done.integration.status}`,\n tone: toneOf(done.integration),\n rows: healthRows(done.integration),\n notes: plan.run\n ? []\n : [\n `\"${cli()} teams health ${done.team.slug} ${product} --mine --run\" checks it now.`,\n ],\n }),\n );\n }\n if (plan.run && plan.product) {\n const product = plan.product;\n const done = await client.call((token) =>\n runTeamHealthCheck(host, token, { ...team, product }),\n );\n return ctx.succeed(\n { host, ...done },\n ctx.ui.result({\n title: `${done.integration.productName} on ${done.team.slug}: ${done.integration.status}`,\n tone: toneOf(done.integration),\n rows: healthRows(done.integration),\n }),\n );\n }\n const list = await client.call((token) =>\n listTeamHealth(host, token, team),\n );\n const rows = plan.product\n ? list.integrations.filter((row) => row.slug === plan.product)\n : list.integrations;\n if (plan.product && rows.length === 0) {\n throw invalidStateError(\n `${list.team.slug} has not connected ${plan.product}, so it has no health to show.`,\n `\"${cli()} teams health ${list.team.slug}\" lists what it has connected.`,\n );\n }\n const data = { host, ...list, integrations: rows };\n if (plan.product) {\n const row = rows[0]!;\n return ctx.succeed(\n data,\n ctx.ui.result({\n title: `${row.productName} on ${list.team.slug}: ${row.status}`,\n tone: toneOf(row),\n rows: healthRows(row),\n notes: [\n `\"${cli()} teams health ${list.team.slug} ${row.slug} --run\" checks it now.`,\n ],\n }),\n );\n }\n return ctx.succeed(\n data,\n ctx.ui.result({\n title:\n rows.length === 0\n ? `${list.team.slug} has no connected integrations`\n : `Integration health on ${list.team.slug}`,\n tone:\n rows.length === 0\n ? 'warn'\n : rows.some((row) => row.status === 'unhealthy')\n ? 'err'\n : rows.some((row) => row.status !== 'healthy')\n ? 'warn'\n : 'ok',\n rows: rows.map((row): ResultRow => [\n row.slug,\n `${row.status}${row.statusReason ? ` · ${row.statusReason}` : ''}${row.lastCheckedAt ? ` · checked ${row.lastCheckedAt.slice(0, 10)}` : ' · never checked'}`,\n ]),\n notes:\n rows.length === 0\n ? []\n : [\n `\"${cli()} teams health ${list.team.slug} <product> --run\" checks one now.`,\n ],\n }),\n );\n }\n\n case 'workspace-list': {\n const list = await client.call((token) =>\n listTeamWorkspaces(host, token, team),\n );\n return ctx.succeed(\n { host, ...list },\n ctx.ui.result({\n title:\n list.workspaces.length === 0\n ? `${list.team.slug} has no workspaces`\n : `Workspaces of ${list.team.slug}`,\n tone: list.workspaces.length === 0 ? 'warn' : 'ok',\n rows: list.workspaces.map((workspace): ResultRow => [\n workspace.slug,\n [\n workspace.label ?? workspace.name,\n ...(workspace.isDefault ? ['default'] : []),\n ...(workspace.visible ? [] : ['hidden by the team']),\n ].join(' · '),\n ]),\n notes: [\n `\"${cli()} teams workspace default ${list.team.slug} <workspace>\" sets the one the team lands on.`,\n ],\n }),\n );\n }\n\n case 'workspace-default': {\n const done = await client.call((token) =>\n setTeamDefaultWorkspace(host, token, team, plan.workspace),\n );\n return ctx.succeed(\n { host, ...done },\n ctx.ui.result({\n title: done.changed\n ? `${done.team.slug} now lands on ${done.workspace.label ?? done.workspace.name}`\n : `${done.workspace.label ?? done.workspace.name} is already ${done.team.slug}'s default`,\n rows: [['Was', done.previous?.slug ?? '—']],\n notes: ['A member who picked their own default keeps theirs.'],\n }),\n );\n }\n }\n}\n\nfunction confirmUnless(\n yes: boolean,\n confirm: Confirmation,\n): { confirm?: Confirmation } {\n return yes ? {} : { confirm };\n}\n\n/**\n * A change that takes something away: asked at a terminal; a script, an\n * agent run or `--json` passes `--yes` instead. Asked before any request.\n */\nexport async function confirmChange(\n ctx: CliContext,\n args: TeamsArgs,\n confirm: Confirmation,\n): Promise<void> {\n if (!canPrompt(ctx, args)) {\n throw invalidStateError(\n confirm.what,\n `Re-run with --yes: ${confirm.command}`,\n );\n }\n const { ask } = args;\n const confirmed = ask\n ? /^y(es)?$/i.test((await ask(confirm.question)).trim())\n : await promptYesNo(confirm.question);\n if (!confirmed) {\n throw invalidStateError(\n `Not confirmed: ${confirm.what}`,\n 'Nothing was changed.',\n );\n }\n}\n\nfunction groupRow(group: TeamGroup): ResultRow {\n return [\n group.kind === 'predefined'\n ? `${group.name} (predefined)`\n : group.kind === 'everyone'\n ? `${group.name} (everyone in no other group)`\n : group.name,\n [\n group.description ?? 'no description',\n group.kind === 'everyone'\n ? 'members: everyone on the team in no other group'\n : `members: ${group.members.length === 0 ? 'none' : group.members.map((member) => member.email ?? member.userId).join(', ')}`,\n `products: ${group.products.length === 0 ? 'none (no narrowing)' : group.products.map((product) => product.slug).join(', ')}`,\n ],\n ];\n}\n\nfunction healthRows(row: TeamHealthRow): ResultRow[] {\n return [\n ['Status', row.status],\n ...(row.statusReason ? [['Why', row.statusReason] as const] : []),\n ['Last checked', row.lastCheckedAt ?? 'never'],\n ['Last success', row.lastSuccessAt ?? '—'],\n ['Last failure', row.lastFailureAt ?? '—'],\n ...(row.lastErrorMessage\n ? [['Last error', row.lastErrorMessage] as const]\n : []),\n ...(row.tokenExpiresAt\n ? [['Token expires', row.tokenExpiresAt] as const]\n : []),\n ];\n}\n\nfunction toneOf(row: TeamHealthRow) {\n return row.status === 'healthy'\n ? ('ok' as const)\n : row.status === 'unhealthy'\n ? ('err' as const)\n : ('warn' as const);\n}\n\nfunction stringFlag(value: unknown): string | undefined {\n return typeof value === 'string' ? value.trim() : undefined;\n}\n\n/** `--products a,b`: the list; `--products none` (or empty): no products. */\nfunction productsFlag(value: unknown): string[] | undefined {\n if (typeof value !== 'string') return undefined;\n const trimmed = value.trim().toLowerCase();\n if (trimmed === '' || trimmed === 'none') return [];\n return [\n ...new Set(\n trimmed\n .split(',')\n .map((slug) => slug.trim())\n .filter(Boolean)\n .map((slug) => slugOf(slug, 'product')),\n ),\n ];\n}\n\nfunction groupOf(value: string | undefined, team: string): string {\n const group = value?.trim();\n if (group) return group;\n throw usageError(\n 'Name the group, by name or id.',\n `\"${cli()} teams groups list ${team}\" lists them.`,\n );\n}\n\nfunction quote(value: string): string {\n return /^[A-Za-z0-9._-]+$/.test(value) ? value : `\"${value}\"`;\n}\n\nfunction noExtra(extra: readonly string[]) {\n if (extra.length > 0) {\n throw usageError(\n `Unexpected argument \"${extra[0]}\".`,\n 'See \"ekanos teams --help\".',\n );\n }\n}\n\nfunction slugOf(value: string | undefined, what: 'team' | 'product'): string {\n const slug = value?.trim().toLowerCase();\n if (slug && /^[a-z0-9][a-z0-9-]*$/.test(slug)) return slug;\n throw usageError(\n value ? `\"${value}\" is not a ${what} slug.` : `Name the ${what}.`,\n what === 'team'\n ? '\"ekanos teams list\" lists the teams, e.g. \"ekanos teams health bank-a\".'\n : '\"ekanos catalog\" lists the products, e.g. \"ekanos teams health bank-a zendesk\".',\n );\n}\n\nfunction emailOf(value: string | undefined): string {\n const email = value?.trim().toLowerCase();\n if (email && /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email)) return email;\n throw usageError(\n value ? `\"${value}\" is not an email address.` : 'Name the person by email.',\n 'e.g. \"ekanos teams members resend bank-a ana@bank-a.com\".',\n );\n}\n"]}
@@ -22,11 +22,16 @@ export interface SourceOptions {
22
22
  fromPath?: string;
23
23
  env?: Record<string, string | undefined>;
24
24
  }
25
- /** Every `*.contract.json` of `dir` for `integration`, highest contract version within `line` first. */
25
+ /**
26
+ * Every `*.contract.json` of `dir` for `integration` (a reference: `slug` or
27
+ * `ns/slug`; files are named by its token), highest contract version within
28
+ * `line` first. A namespaced reference never matches a global file of the same
29
+ * slug, nor the reverse.
30
+ */
26
31
  export declare function contractsInDir(dir: string, integration: string, line: string): Contract[];
27
32
  export declare function dirSource(dir: string): ContractSource;
28
33
  export declare function pathSource(projectPath: string): ContractSource;
29
- /** The committed pin: `<contractsDir>/<integration>@<version>.contract.json`. */
34
+ /** The committed pin: `<contractsDir>/<token>@<version>.contract.json`, always flat. */
30
35
  export declare function snapshotFile(project: ExperienceProject, integration: string, line: string): string;
31
36
  export declare function snapshotSource(project: ExperienceProject): ContractSource;
32
37
  /** Sources in resolution order: explicit flags, env, then (optionally) the snapshot. */
@@ -1,4 +1,4 @@
1
- import { compareSemver, compatLine, verifyContract, } from '@ekanos/integration-schema';
1
+ import { compareSemver, compatLine, contractMatchesRef, integrationRefToken, snapshotFileName, verifyContract, } from '@ekanos/integration-schema';
2
2
  import * as fs from 'node:fs';
3
3
  import * as path from 'node:path';
4
4
  import { notFoundError, validationError } from '../errors.js';
@@ -17,8 +17,16 @@ function readContractFile(file) {
17
17
  }
18
18
  return verified.contract;
19
19
  }
20
- /** Every `*.contract.json` of `dir` for `integration`, highest contract version within `line` first. */
20
+ /**
21
+ * Every `*.contract.json` of `dir` for `integration` (a reference: `slug` or
22
+ * `ns/slug`; files are named by its token), highest contract version within
23
+ * `line` first. A namespaced reference never matches a global file of the same
24
+ * slug, nor the reverse.
25
+ */
21
26
  export function contractsInDir(dir, integration, line) {
27
+ const token = integrationRefToken(integration);
28
+ if (token === null)
29
+ return [];
22
30
  let names;
23
31
  try {
24
32
  names = fs.readdirSync(dir).filter((n) => n.endsWith('.contract.json'));
@@ -28,13 +36,12 @@ export function contractsInDir(dir, integration, line) {
28
36
  }
29
37
  const found = [];
30
38
  for (const name of names) {
31
- if (!name.startsWith(`${integration}@`) &&
32
- !name.startsWith(`${integration}.`)) {
39
+ if (!name.startsWith(`${token}@`) && !name.startsWith(`${token}.`)) {
33
40
  continue;
34
41
  }
35
42
  const contract = readContractFile(path.join(dir, name));
36
43
  if (contract &&
37
- contract.integration === integration &&
44
+ contractMatchesRef(contract, integration) &&
38
45
  contract.compatLine === line) {
39
46
  found.push(contract);
40
47
  }
@@ -60,7 +67,7 @@ export function pathSource(projectPath) {
60
67
  }
61
68
  const contract = readContractFile(file);
62
69
  if (!contract ||
63
- contract.integration !== integration ||
70
+ !contractMatchesRef(contract, integration) ||
64
71
  contract.compatLine !== line) {
65
72
  return null;
66
73
  }
@@ -68,9 +75,9 @@ export function pathSource(projectPath) {
68
75
  },
69
76
  };
70
77
  }
71
- /** The committed pin: `<contractsDir>/<integration>@<version>.contract.json`. */
78
+ /** The committed pin: `<contractsDir>/<token>@<version>.contract.json`, always flat. */
72
79
  export function snapshotFile(project, integration, line) {
73
- return path.join(project.contractsDir, `${integration}@${line}.contract.json`);
80
+ return path.join(project.contractsDir, snapshotFileName(integration, line));
74
81
  }
75
82
  export function snapshotSource(project) {
76
83
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"contract-sources.js","sourceRoot":"","sources":["../../src/experience/contract-sources.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type Contract,\n compareSemver,\n compatLine,\n verifyContract,\n} from '@ekanos/integration-schema';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport { notFoundError, validationError } from '../errors';\nimport type { ExperienceProject } from './project';\n\n/** Where an integration's contract came from, for messages and `sync` bookkeeping. */\nexport interface ResolvedContract {\n contract: Contract;\n origin: string;\n kind: 'dir' | 'path' | 'snapshot';\n}\n\n/**\n * A pluggable contract source. The dir/path/snapshot sources below are the\n * offline defaults; the harness resolver (catalog, published packages) plugs\n * in here as another source, so `add`/`sync` never learn where contracts live.\n */\nexport interface ContractSource {\n name: string;\n resolve(\n integration: string,\n line: string,\n ): Promise<ResolvedContract | null> | ResolvedContract | null;\n}\n\nexport interface SourceOptions {\n /** A directory of `*.contract.json` (the monorepo contracts folder or a registry mirror). */\n fromDir?: string;\n /** An integration project directory; its `contract.json` is read. */\n fromPath?: string;\n env?: Record<string, string | undefined>;\n}\n\nfunction readContractFile(file: string): Contract | null {\n let json: unknown;\n try {\n json = JSON.parse(fs.readFileSync(file, 'utf8'));\n } catch {\n return null;\n }\n const verified = verifyContract(json);\n if (!verified.contract || verified.problems.length > 0) {\n const first = verified.problems[0];\n throw validationError(\n `${file} is not a valid contract: ${first ? `${first.rule}: ${first.message}` : 'unreadable'}`,\n 'Regenerate it with \"ekanos contract\" in the integration, or point at a valid contracts directory.',\n );\n }\n\n return verified.contract;\n}\n\n/** Every `*.contract.json` of `dir` for `integration`, highest contract version within `line` first. */\nexport function contractsInDir(\n dir: string,\n integration: string,\n line: string,\n): Contract[] {\n let names: string[];\n try {\n names = fs.readdirSync(dir).filter((n) => n.endsWith('.contract.json'));\n } catch {\n return [];\n }\n const found: Contract[] = [];\n for (const name of names) {\n if (\n !name.startsWith(`${integration}@`) &&\n !name.startsWith(`${integration}.`)\n ) {\n continue;\n }\n const contract = readContractFile(path.join(dir, name));\n if (\n contract &&\n contract.integration === integration &&\n contract.compatLine === line\n ) {\n found.push(contract);\n }\n }\n\n return found.sort((a, b) =>\n compareSemver(b.contractVersion, a.contractVersion),\n );\n}\n\nexport function dirSource(dir: string): ContractSource {\n return {\n name: `dir ${dir}`,\n resolve(integration, line) {\n const [best] = contractsInDir(dir, integration, line);\n\n return best ? { contract: best, origin: dir, kind: 'dir' } : null;\n },\n };\n}\n\nexport function pathSource(projectPath: string): ContractSource {\n return {\n name: `path ${projectPath}`,\n resolve(integration, line) {\n const file = path.join(path.resolve(projectPath), 'contract.json');\n if (!fs.existsSync(file)) {\n throw notFoundError(\n `${file} does not exist.`,\n 'Run \"ekanos contract\" in that integration to derive its contract.json.',\n );\n }\n const contract = readContractFile(file);\n if (\n !contract ||\n contract.integration !== integration ||\n contract.compatLine !== line\n ) {\n return null;\n }\n\n return { contract, origin: file, kind: 'path' };\n },\n };\n}\n\n/** The committed pin: `<contractsDir>/<integration>@<version>.contract.json`. */\nexport function snapshotFile(\n project: ExperienceProject,\n integration: string,\n line: string,\n): string {\n return path.join(\n project.contractsDir,\n `${integration}@${line}.contract.json`,\n );\n}\n\nexport function snapshotSource(project: ExperienceProject): ContractSource {\n return {\n name: 'committed snapshot',\n resolve(integration, line) {\n const file = snapshotFile(project, integration, line);\n const contract = fs.existsSync(file) ? readContractFile(file) : null;\n\n return contract ? { contract, origin: file, kind: 'snapshot' } : null;\n },\n };\n}\n\n/** Sources in resolution order: explicit flags, env, then (optionally) the snapshot. */\nexport function defaultSources(\n project: ExperienceProject,\n options: SourceOptions,\n extra: readonly ContractSource[] = [],\n includeSnapshot = true,\n): ContractSource[] {\n const sources: ContractSource[] = [];\n if (options.fromPath) sources.push(pathSource(options.fromPath));\n if (options.fromDir) sources.push(dirSource(path.resolve(options.fromDir)));\n const envDir = options.env?.EKANOS_CONTRACTS_DIR;\n if (!options.fromDir && envDir) sources.push(dirSource(path.resolve(envDir)));\n sources.push(...extra);\n if (includeSnapshot) sources.push(snapshotSource(project));\n\n return sources;\n}\n\nexport async function resolveContract(\n sources: readonly ContractSource[],\n integration: string,\n line: string,\n): Promise<ResolvedContract> {\n for (const source of sources) {\n const hit = await source.resolve(integration, line);\n if (hit) return hit;\n }\n\n throw notFoundError(\n `No contract for ${integration}@${line} (looked in: ${sources.map((s) => s.name).join(', ') || 'nothing'}).`,\n 'Pass --from-dir <contracts folder> or --from-path <integration project>, or set EKANOS_CONTRACTS_DIR.',\n );\n}\n\n/** Line for a package version, re-exported so callers need no schema import. */\nexport { compatLine };\n"]}
1
+ {"version":3,"file":"contract-sources.js","sourceRoot":"","sources":["../../src/experience/contract-sources.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type Contract,\n compareSemver,\n compatLine,\n contractMatchesRef,\n integrationRefToken,\n snapshotFileName,\n verifyContract,\n} from '@ekanos/integration-schema';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport { notFoundError, validationError } from '../errors';\nimport type { ExperienceProject } from './project';\n\n/** Where an integration's contract came from, for messages and `sync` bookkeeping. */\nexport interface ResolvedContract {\n contract: Contract;\n origin: string;\n kind: 'dir' | 'path' | 'snapshot';\n}\n\n/**\n * A pluggable contract source. The dir/path/snapshot sources below are the\n * offline defaults; the harness resolver (catalog, published packages) plugs\n * in here as another source, so `add`/`sync` never learn where contracts live.\n */\nexport interface ContractSource {\n name: string;\n resolve(\n integration: string,\n line: string,\n ): Promise<ResolvedContract | null> | ResolvedContract | null;\n}\n\nexport interface SourceOptions {\n /** A directory of `*.contract.json` (the monorepo contracts folder or a registry mirror). */\n fromDir?: string;\n /** An integration project directory; its `contract.json` is read. */\n fromPath?: string;\n env?: Record<string, string | undefined>;\n}\n\nfunction readContractFile(file: string): Contract | null {\n let json: unknown;\n try {\n json = JSON.parse(fs.readFileSync(file, 'utf8'));\n } catch {\n return null;\n }\n const verified = verifyContract(json);\n if (!verified.contract || verified.problems.length > 0) {\n const first = verified.problems[0];\n throw validationError(\n `${file} is not a valid contract: ${first ? `${first.rule}: ${first.message}` : 'unreadable'}`,\n 'Regenerate it with \"ekanos contract\" in the integration, or point at a valid contracts directory.',\n );\n }\n\n return verified.contract;\n}\n\n/**\n * Every `*.contract.json` of `dir` for `integration` (a reference: `slug` or\n * `ns/slug`; files are named by its token), highest contract version within\n * `line` first. A namespaced reference never matches a global file of the same\n * slug, nor the reverse.\n */\nexport function contractsInDir(\n dir: string,\n integration: string,\n line: string,\n): Contract[] {\n const token = integrationRefToken(integration);\n if (token === null) return [];\n let names: string[];\n try {\n names = fs.readdirSync(dir).filter((n) => n.endsWith('.contract.json'));\n } catch {\n return [];\n }\n const found: Contract[] = [];\n for (const name of names) {\n if (!name.startsWith(`${token}@`) && !name.startsWith(`${token}.`)) {\n continue;\n }\n const contract = readContractFile(path.join(dir, name));\n if (\n contract &&\n contractMatchesRef(contract, integration) &&\n contract.compatLine === line\n ) {\n found.push(contract);\n }\n }\n\n return found.sort((a, b) =>\n compareSemver(b.contractVersion, a.contractVersion),\n );\n}\n\nexport function dirSource(dir: string): ContractSource {\n return {\n name: `dir ${dir}`,\n resolve(integration, line) {\n const [best] = contractsInDir(dir, integration, line);\n\n return best ? { contract: best, origin: dir, kind: 'dir' } : null;\n },\n };\n}\n\nexport function pathSource(projectPath: string): ContractSource {\n return {\n name: `path ${projectPath}`,\n resolve(integration, line) {\n const file = path.join(path.resolve(projectPath), 'contract.json');\n if (!fs.existsSync(file)) {\n throw notFoundError(\n `${file} does not exist.`,\n 'Run \"ekanos contract\" in that integration to derive its contract.json.',\n );\n }\n const contract = readContractFile(file);\n if (\n !contract ||\n !contractMatchesRef(contract, integration) ||\n contract.compatLine !== line\n ) {\n return null;\n }\n\n return { contract, origin: file, kind: 'path' };\n },\n };\n}\n\n/** The committed pin: `<contractsDir>/<token>@<version>.contract.json`, always flat. */\nexport function snapshotFile(\n project: ExperienceProject,\n integration: string,\n line: string,\n): string {\n return path.join(project.contractsDir, snapshotFileName(integration, line));\n}\n\nexport function snapshotSource(project: ExperienceProject): ContractSource {\n return {\n name: 'committed snapshot',\n resolve(integration, line) {\n const file = snapshotFile(project, integration, line);\n const contract = fs.existsSync(file) ? readContractFile(file) : null;\n\n return contract ? { contract, origin: file, kind: 'snapshot' } : null;\n },\n };\n}\n\n/** Sources in resolution order: explicit flags, env, then (optionally) the snapshot. */\nexport function defaultSources(\n project: ExperienceProject,\n options: SourceOptions,\n extra: readonly ContractSource[] = [],\n includeSnapshot = true,\n): ContractSource[] {\n const sources: ContractSource[] = [];\n if (options.fromPath) sources.push(pathSource(options.fromPath));\n if (options.fromDir) sources.push(dirSource(path.resolve(options.fromDir)));\n const envDir = options.env?.EKANOS_CONTRACTS_DIR;\n if (!options.fromDir && envDir) sources.push(dirSource(path.resolve(envDir)));\n sources.push(...extra);\n if (includeSnapshot) sources.push(snapshotSource(project));\n\n return sources;\n}\n\nexport async function resolveContract(\n sources: readonly ContractSource[],\n integration: string,\n line: string,\n): Promise<ResolvedContract> {\n for (const source of sources) {\n const hit = await source.resolve(integration, line);\n if (hit) return hit;\n }\n\n throw notFoundError(\n `No contract for ${integration}@${line} (looked in: ${sources.map((s) => s.name).join(', ') || 'nothing'}).`,\n 'Pass --from-dir <contracts folder> or --from-path <integration project>, or set EKANOS_CONTRACTS_DIR.',\n );\n}\n\n/** Line for a package version, re-exported so callers need no schema import. */\nexport { compatLine };\n"]}
@@ -86,7 +86,10 @@ export function analyzeDefinition(project, loaded, pinned) {
86
86
  continue;
87
87
  let dsl;
88
88
  try {
89
- dsl = loaded.serializeWorkflowTemplate(template, { effectOf });
89
+ dsl = loaded.serializeWorkflowTemplate(template, {
90
+ effectOf,
91
+ experience: project.slug,
92
+ });
90
93
  }
91
94
  catch (error) {
92
95
  findings.push(err(`${where}: ${error instanceof Error ? error.message : String(error)}`, 'Fix the template.', project.entry));
@@ -1 +1 @@
1
- {"version":3,"file":"definition-checks.js","sourceRoot":"","sources":["../../src/experience/definition-checks.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type ExperienceManifest,\n type ExperienceSurfaces,\n ExperienceSurfacesSchema,\n type Finding,\n type WorkflowTemplate,\n WorkflowTemplateSchema,\n EKANOS_CHECK_STAGE_IDS,\n buildExperienceSurfaces,\n canonicalJson,\n sha256Hex,\n validateAgainstSchema,\n workflowTemplateProblems,\n} from '@ekanos/integration-schema';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport type {\n LoadedExperienceDefinition,\n LoadedExperienceModule,\n} from './definition-shape';\nimport { declaredOperationKeys } from './integrations-codegen';\nimport { type PinnedIntegration, effectLookup } from './pins';\nimport type { ExperienceProject } from './project';\n\nexport const DEFINITION_CHECK = 'checks/experience-definition';\nexport const SURFACES_CHECK = EKANOS_CHECK_STAGE_IDS.experienceSurfaces;\n\nconst err = (message: string, hint: string, file?: string): Finding => ({\n check: DEFINITION_CHECK,\n severity: 'error',\n message,\n hint,\n ...(file ? { file } : {}),\n});\n\nconst warn = (message: string, hint: string, file?: string): Finding => ({\n check: DEFINITION_CHECK,\n severity: 'warn',\n message,\n hint,\n ...(file ? { file } : {}),\n});\n\nexport interface DefinitionAnalysis {\n findings: Finding[];\n workflows: WorkflowTemplate[];\n}\n\n/**\n * Cross-check the loaded definition against `ekanos.json` and the pinned\n * contracts: every integration a widget, page, review section or workflow step names\n * must be declared, every operation must be in that integration's allowlist, the\n * review queue reads only, and each template serializes to the engine's DSL.\n */\nexport function analyzeDefinition(\n project: ExperienceProject,\n loaded: LoadedExperienceModule,\n pinned: readonly PinnedIntegration[],\n): DefinitionAnalysis {\n const { definition } = loaded;\n const findings: Finding[] = [];\n const workflows: WorkflowTemplate[] = [];\n const declaredIntegrations = new Map(\n project.integrations.map((u) => [u.name, u]),\n );\n const declared = new Map(\n project.integrations.map((u) => [\n u.name,\n new Set(declaredOperationKeys(u)),\n ]),\n );\n const contractOps = new Map(\n pinned.map(({ use, contract }) => [\n use.name,\n new Map(contract.operations.map((op) => [`${op.kind}/${op.name}`, op])),\n ]),\n );\n\n if (definition.slug !== project.slug) {\n findings.push(\n err(\n `the definition's slug \"${definition.slug}\" differs from ekanos.json \"${project.slug}\".`,\n 'Make them equal.',\n project.entry,\n ),\n );\n }\n\n const checkIntegration = (integration: string, owner: string) => {\n if (!declaredIntegrations.has(integration)) {\n findings.push(\n err(\n `${owner} uses integration \"${integration}\", which ekanos.json \"integrations\" does not declare.`,\n `Add it with \"ekanos add ${integration}@<version>\".`,\n project.entry,\n ),\n );\n\n return false;\n }\n\n return true;\n };\n\n for (const widget of definition.widgets) {\n for (const integration of widget.integrations)\n checkIntegration(integration, `widget \"${widget.id}\"`);\n }\n for (const page of definition.pages) {\n for (const integration of page.integrations ?? [])\n checkIntegration(integration, `page \"${page.id}\"`);\n }\n\n findings.push(...checkSurfaces(project, definition));\n\n for (const section of definition.reviewQueue?.sections ?? []) {\n if (\n !checkIntegration(section.integration, `review section \"${section.id}\"`)\n )\n continue;\n if (!declared.get(section.integration)?.has(section.read)) {\n findings.push(\n err(\n `review section \"${section.id}\" reads ${section.read}, which integration \"${section.integration}\" does not declare.`,\n 'Add the operation to the integration in ekanos.json, or read another one.',\n project.entry,\n ),\n );\n } else if (\n contractOps.get(section.integration)?.get(section.read)?.effect !== 'read'\n ) {\n findings.push(\n err(\n `review section \"${section.id}\" reads ${section.read}, which is not a read operation.`,\n 'The review queue is reads-only; writes belong behind a workflow approval.',\n project.entry,\n ),\n );\n }\n }\n\n const effectOf = effectLookup(pinned);\n for (const template of definition.workflows) {\n const where = `workflow \"${template.id}\"`;\n let steps: ReturnType<typeof template.build>;\n try {\n steps = template.build();\n } catch (error) {\n findings.push(\n err(\n `${where}: build() threw: ${error instanceof Error ? error.message : String(error)}`,\n 'Fix the template.',\n project.entry,\n ),\n );\n continue;\n }\n\n let stepsOk = true;\n for (const step of steps) {\n if (step.type !== 'tool' || !step.integration || !step.op) continue;\n if (!checkIntegration(step.integration, `${where} step \"${step.id}\"`)) {\n stepsOk = false;\n } else if (!declared.get(step.integration)?.has(step.op)) {\n stepsOk = false;\n findings.push(\n err(\n `${where} step \"${step.id}\" calls ${step.integration} ${step.op}, which the integration does not declare.`,\n 'Add the operation to the integration\\'s \"operations\" in ekanos.json (ekanos add --ops).',\n project.entry,\n ),\n );\n }\n }\n if (!stepsOk) continue;\n\n let dsl: unknown;\n try {\n dsl = loaded.serializeWorkflowTemplate(template, { effectOf });\n } catch (error) {\n findings.push(\n err(\n `${where}: ${error instanceof Error ? error.message : String(error)}`,\n 'Fix the template.',\n project.entry,\n ),\n );\n continue;\n }\n const parsed = WorkflowTemplateSchema.safeParse(dsl);\n if (!parsed.success) {\n findings.push(\n err(\n `${where} does not serialize to a valid workflow: ${parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; ')}`,\n 'Fix the step definitions.',\n project.entry,\n ),\n );\n continue;\n }\n for (const problem of workflowTemplateProblems(parsed.data)) {\n findings.push(\n err(`${where}: ${problem}.`, 'Fix the template.', project.entry),\n );\n }\n\n const gated = new Set<string>();\n const preds = new Map<string, string[]>();\n for (const e of parsed.data.edges)\n preds.set(e.to, [...(preds.get(e.to) ?? []), e.from]);\n const hasGate = (id: string, seen = new Set<string>()): boolean => {\n if (seen.has(id)) return false;\n seen.add(id);\n\n return (preds.get(id) ?? []).some(\n (p) =>\n parsed.data.steps.find((s) => s.id === p)?.type === 'approval_gate' ||\n hasGate(p, seen),\n );\n };\n for (const s of parsed.data.steps) {\n if (s.type === 'fusion_tool' && s.effect === 'write' && !hasGate(s.id)) {\n gated.add(s.id);\n }\n }\n for (const id of gated) {\n findings.push(\n warn(\n `${where}: write step \"${id}\" has no approval gate upstream.`,\n 'Put step.approval(...) before a write so a person confirms it.',\n project.entry,\n ),\n );\n }\n\n workflows.push(parsed.data);\n }\n\n return { findings, workflows };\n}\n\n// ─── surfaces ───────────────────────────────────────────────────────────────\n\n/**\n * The surfaces contract: page kinds, canvas widgets, routes and the suggested\n * layout must be well formed and refer only to what the experience declares.\n * The same rules `defineExperience` enforces, re-run on the loaded definition\n * so a definition built by an older SDK, or by hand, cannot slip past.\n */\nexport function checkSurfaces(\n project: ExperienceProject,\n definition: LoadedExperienceDefinition,\n): Finding[] {\n const built = buildSurfaces(project, definition);\n const parsed = ExperienceSurfacesSchema.safeParse(built);\n if (parsed.success) return [];\n\n return parsed.error.issues.map((issue) => ({\n check: SURFACES_CHECK,\n severity: 'error' as const,\n message: `${issue.path.length > 0 ? `${issue.path.join('.')}: ` : ''}${issue.message}`,\n hint: 'Fix the page kinds, canvas widgets or suggestedLayout in the experience definition.',\n file: project.entry,\n }));\n}\n\n/** `dist/surfaces.json`: the surfaces and suggested layout as data, no code. */\nexport function buildSurfaces(\n project: ExperienceProject,\n definition: LoadedExperienceDefinition,\n): ExperienceSurfaces {\n return buildExperienceSurfaces(project.slug, definition);\n}\n\n// ─── fixtures ───────────────────────────────────────────────────────────────\n\nconst FIXTURE_NAME = /^(tool|action)-(.+)\\.(default|empty|error)\\.json$/;\n\n/** `fixtures/<integration>/<kind>-<name>.<variant>.json` must satisfy the pinned output schema. */\nexport function checkFixtures(\n project: ExperienceProject,\n pinned: readonly PinnedIntegration[],\n): Finding[] {\n const findings: Finding[] = [];\n const root = path.join(project.dir, 'fixtures');\n if (!fs.existsSync(root)) return findings;\n\n for (const { use, contract } of pinned) {\n const dir = path.join(root, use.name);\n if (!fs.existsSync(dir)) continue;\n for (const name of fs.readdirSync(dir)) {\n const rel = `fixtures/${use.name}/${name}`;\n const match = FIXTURE_NAME.exec(name);\n if (!match) {\n findings.push(\n warn(\n `${rel} is not <kind>-<name>.<default|empty|error>.json.`,\n 'Rename it so the harness can find it.',\n rel,\n ),\n );\n continue;\n }\n const [, kind, op, variant] = match;\n if (variant === 'error') continue;\n const operation = contract.operations.find(\n (o) => o.kind === kind && o.name === op,\n );\n if (!operation) {\n findings.push(\n err(\n `${rel}: ${use.name}@${use.version} has no ${kind}/${op}.`,\n 'Delete the fixture or fix its name.',\n rel,\n ),\n );\n continue;\n }\n if (operation.opaque.output) continue;\n let value: unknown;\n try {\n value = JSON.parse(fs.readFileSync(path.join(dir, name), 'utf8'));\n } catch {\n findings.push(err(`${rel} is not valid JSON.`, 'Fix the syntax.', rel));\n continue;\n }\n const problems = validateAgainstSchema(operation.output, value);\n if (problems.length > 0) {\n findings.push(\n err(\n `${rel} violates the pinned output schema: ${problems[0]}`,\n 'A fixture must satisfy the contract, or the harness would show data the integration can never return.',\n rel,\n ),\n );\n }\n }\n }\n\n return findings;\n}\n\n// ─── manifest ───────────────────────────────────────────────────────────────\n\nexport function buildManifest(input: {\n project: ExperienceProject;\n definition: LoadedExperienceDefinition;\n pinned: readonly PinnedIntegration[];\n workflows: readonly WorkflowTemplate[];\n version: string;\n sdk: string;\n surfaces: ExperienceSurfaces;\n}): ExperienceManifest {\n const { project, definition, pinned } = input;\n const body = {\n schemaVersion: 1 as const,\n slug: project.slug,\n form: 'composed' as const,\n version: input.version,\n sdk: input.sdk,\n integrations: project.integrations,\n contractRefs: pinned.map(({ use, contract }) => ({\n integration: use.name,\n version: use.version,\n contractVersion: contract.contractVersion,\n digest: contract.digest,\n })),\n ...(definition.sidebar ? { sidebar: definition.sidebar } : {}),\n widgets: definition.widgets.map((w) => ({\n id: w.id,\n title: w.title,\n integrations: [...w.integrations],\n ...(w.width ? { width: w.width } : {}),\n ...(w.isCollapsible === undefined\n ? {}\n : { isCollapsible: w.isCollapsible }),\n ...(w.aiFooterEnabled === undefined\n ? {}\n : { aiFooterEnabled: w.aiFooterEnabled }),\n })),\n pages: definition.pages.map((p) => ({\n id: p.id,\n ...(p.path === undefined ? {} : { path: p.path }),\n title: p.title,\n integrations: [...(p.integrations ?? [])],\n ...(p.kind === undefined ? {} : { kind: p.kind }),\n ...(p.widgets === undefined ? {} : { widgets: [...p.widgets] }),\n ...(p.routes && p.routes.length > 0\n ? { routes: p.routes.map((r) => ({ path: r.path, title: r.title })) }\n : {}),\n })),\n surfacesDigest: input.surfaces.digest,\n workflowTemplates: [...input.workflows],\n ...(definition.reviewQueue\n ? {\n reviewQueue: {\n readsOnly: true as const,\n sections: definition.reviewQueue.sections.map((s) => ({\n id: s.id,\n integration: s.integration,\n read: s.read,\n })),\n },\n }\n : {}),\n };\n\n return {\n ...body,\n digest: `sha256:${sha256Hex(canonicalJson(body))}`,\n };\n}\n"]}
1
+ {"version":3,"file":"definition-checks.js","sourceRoot":"","sources":["../../src/experience/definition-checks.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type ExperienceManifest,\n type ExperienceSurfaces,\n ExperienceSurfacesSchema,\n type Finding,\n type WorkflowTemplate,\n WorkflowTemplateSchema,\n EKANOS_CHECK_STAGE_IDS,\n buildExperienceSurfaces,\n canonicalJson,\n sha256Hex,\n validateAgainstSchema,\n workflowTemplateProblems,\n} from '@ekanos/integration-schema';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nimport type {\n LoadedExperienceDefinition,\n LoadedExperienceModule,\n} from './definition-shape';\nimport { declaredOperationKeys } from './integrations-codegen';\nimport { type PinnedIntegration, effectLookup } from './pins';\nimport type { ExperienceProject } from './project';\n\nexport const DEFINITION_CHECK = 'checks/experience-definition';\nexport const SURFACES_CHECK = EKANOS_CHECK_STAGE_IDS.experienceSurfaces;\n\nconst err = (message: string, hint: string, file?: string): Finding => ({\n check: DEFINITION_CHECK,\n severity: 'error',\n message,\n hint,\n ...(file ? { file } : {}),\n});\n\nconst warn = (message: string, hint: string, file?: string): Finding => ({\n check: DEFINITION_CHECK,\n severity: 'warn',\n message,\n hint,\n ...(file ? { file } : {}),\n});\n\nexport interface DefinitionAnalysis {\n findings: Finding[];\n workflows: WorkflowTemplate[];\n}\n\n/**\n * Cross-check the loaded definition against `ekanos.json` and the pinned\n * contracts: every integration a widget, page, review section or workflow step names\n * must be declared, every operation must be in that integration's allowlist, the\n * review queue reads only, and each template serializes to the engine's DSL.\n */\nexport function analyzeDefinition(\n project: ExperienceProject,\n loaded: LoadedExperienceModule,\n pinned: readonly PinnedIntegration[],\n): DefinitionAnalysis {\n const { definition } = loaded;\n const findings: Finding[] = [];\n const workflows: WorkflowTemplate[] = [];\n const declaredIntegrations = new Map(\n project.integrations.map((u) => [u.name, u]),\n );\n const declared = new Map(\n project.integrations.map((u) => [\n u.name,\n new Set(declaredOperationKeys(u)),\n ]),\n );\n const contractOps = new Map(\n pinned.map(({ use, contract }) => [\n use.name,\n new Map(contract.operations.map((op) => [`${op.kind}/${op.name}`, op])),\n ]),\n );\n\n if (definition.slug !== project.slug) {\n findings.push(\n err(\n `the definition's slug \"${definition.slug}\" differs from ekanos.json \"${project.slug}\".`,\n 'Make them equal.',\n project.entry,\n ),\n );\n }\n\n const checkIntegration = (integration: string, owner: string) => {\n if (!declaredIntegrations.has(integration)) {\n findings.push(\n err(\n `${owner} uses integration \"${integration}\", which ekanos.json \"integrations\" does not declare.`,\n `Add it with \"ekanos add ${integration}@<version>\".`,\n project.entry,\n ),\n );\n\n return false;\n }\n\n return true;\n };\n\n for (const widget of definition.widgets) {\n for (const integration of widget.integrations)\n checkIntegration(integration, `widget \"${widget.id}\"`);\n }\n for (const page of definition.pages) {\n for (const integration of page.integrations ?? [])\n checkIntegration(integration, `page \"${page.id}\"`);\n }\n\n findings.push(...checkSurfaces(project, definition));\n\n for (const section of definition.reviewQueue?.sections ?? []) {\n if (\n !checkIntegration(section.integration, `review section \"${section.id}\"`)\n )\n continue;\n if (!declared.get(section.integration)?.has(section.read)) {\n findings.push(\n err(\n `review section \"${section.id}\" reads ${section.read}, which integration \"${section.integration}\" does not declare.`,\n 'Add the operation to the integration in ekanos.json, or read another one.',\n project.entry,\n ),\n );\n } else if (\n contractOps.get(section.integration)?.get(section.read)?.effect !== 'read'\n ) {\n findings.push(\n err(\n `review section \"${section.id}\" reads ${section.read}, which is not a read operation.`,\n 'The review queue is reads-only; writes belong behind a workflow approval.',\n project.entry,\n ),\n );\n }\n }\n\n const effectOf = effectLookup(pinned);\n for (const template of definition.workflows) {\n const where = `workflow \"${template.id}\"`;\n let steps: ReturnType<typeof template.build>;\n try {\n steps = template.build();\n } catch (error) {\n findings.push(\n err(\n `${where}: build() threw: ${error instanceof Error ? error.message : String(error)}`,\n 'Fix the template.',\n project.entry,\n ),\n );\n continue;\n }\n\n let stepsOk = true;\n for (const step of steps) {\n if (step.type !== 'tool' || !step.integration || !step.op) continue;\n if (!checkIntegration(step.integration, `${where} step \"${step.id}\"`)) {\n stepsOk = false;\n } else if (!declared.get(step.integration)?.has(step.op)) {\n stepsOk = false;\n findings.push(\n err(\n `${where} step \"${step.id}\" calls ${step.integration} ${step.op}, which the integration does not declare.`,\n 'Add the operation to the integration\\'s \"operations\" in ekanos.json (ekanos add --ops).',\n project.entry,\n ),\n );\n }\n }\n if (!stepsOk) continue;\n\n let dsl: unknown;\n try {\n dsl = loaded.serializeWorkflowTemplate(template, {\n effectOf,\n experience: project.slug,\n });\n } catch (error) {\n findings.push(\n err(\n `${where}: ${error instanceof Error ? error.message : String(error)}`,\n 'Fix the template.',\n project.entry,\n ),\n );\n continue;\n }\n const parsed = WorkflowTemplateSchema.safeParse(dsl);\n if (!parsed.success) {\n findings.push(\n err(\n `${where} does not serialize to a valid workflow: ${parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; ')}`,\n 'Fix the step definitions.',\n project.entry,\n ),\n );\n continue;\n }\n for (const problem of workflowTemplateProblems(parsed.data)) {\n findings.push(\n err(`${where}: ${problem}.`, 'Fix the template.', project.entry),\n );\n }\n\n const gated = new Set<string>();\n const preds = new Map<string, string[]>();\n for (const e of parsed.data.edges)\n preds.set(e.to, [...(preds.get(e.to) ?? []), e.from]);\n const hasGate = (id: string, seen = new Set<string>()): boolean => {\n if (seen.has(id)) return false;\n seen.add(id);\n\n return (preds.get(id) ?? []).some(\n (p) =>\n parsed.data.steps.find((s) => s.id === p)?.type === 'approval_gate' ||\n hasGate(p, seen),\n );\n };\n for (const s of parsed.data.steps) {\n if (s.type === 'fusion_tool' && s.effect === 'write' && !hasGate(s.id)) {\n gated.add(s.id);\n }\n }\n for (const id of gated) {\n findings.push(\n warn(\n `${where}: write step \"${id}\" has no approval gate upstream.`,\n 'Put step.approval(...) before a write so a person confirms it.',\n project.entry,\n ),\n );\n }\n\n workflows.push(parsed.data);\n }\n\n return { findings, workflows };\n}\n\n// ─── surfaces ───────────────────────────────────────────────────────────────\n\n/**\n * The surfaces contract: page kinds, canvas widgets, routes and the suggested\n * layout must be well formed and refer only to what the experience declares.\n * The same rules `defineExperience` enforces, re-run on the loaded definition\n * so a definition built by an older SDK, or by hand, cannot slip past.\n */\nexport function checkSurfaces(\n project: ExperienceProject,\n definition: LoadedExperienceDefinition,\n): Finding[] {\n const built = buildSurfaces(project, definition);\n const parsed = ExperienceSurfacesSchema.safeParse(built);\n if (parsed.success) return [];\n\n return parsed.error.issues.map((issue) => ({\n check: SURFACES_CHECK,\n severity: 'error' as const,\n message: `${issue.path.length > 0 ? `${issue.path.join('.')}: ` : ''}${issue.message}`,\n hint: 'Fix the page kinds, canvas widgets or suggestedLayout in the experience definition.',\n file: project.entry,\n }));\n}\n\n/** `dist/surfaces.json`: the surfaces and suggested layout as data, no code. */\nexport function buildSurfaces(\n project: ExperienceProject,\n definition: LoadedExperienceDefinition,\n): ExperienceSurfaces {\n return buildExperienceSurfaces(project.slug, definition);\n}\n\n// ─── fixtures ───────────────────────────────────────────────────────────────\n\nconst FIXTURE_NAME = /^(tool|action)-(.+)\\.(default|empty|error)\\.json$/;\n\n/** `fixtures/<integration>/<kind>-<name>.<variant>.json` must satisfy the pinned output schema. */\nexport function checkFixtures(\n project: ExperienceProject,\n pinned: readonly PinnedIntegration[],\n): Finding[] {\n const findings: Finding[] = [];\n const root = path.join(project.dir, 'fixtures');\n if (!fs.existsSync(root)) return findings;\n\n for (const { use, contract } of pinned) {\n const dir = path.join(root, use.name);\n if (!fs.existsSync(dir)) continue;\n for (const name of fs.readdirSync(dir)) {\n const rel = `fixtures/${use.name}/${name}`;\n const match = FIXTURE_NAME.exec(name);\n if (!match) {\n findings.push(\n warn(\n `${rel} is not <kind>-<name>.<default|empty|error>.json.`,\n 'Rename it so the harness can find it.',\n rel,\n ),\n );\n continue;\n }\n const [, kind, op, variant] = match;\n if (variant === 'error') continue;\n const operation = contract.operations.find(\n (o) => o.kind === kind && o.name === op,\n );\n if (!operation) {\n findings.push(\n err(\n `${rel}: ${use.name}@${use.version} has no ${kind}/${op}.`,\n 'Delete the fixture or fix its name.',\n rel,\n ),\n );\n continue;\n }\n if (operation.opaque.output) continue;\n let value: unknown;\n try {\n value = JSON.parse(fs.readFileSync(path.join(dir, name), 'utf8'));\n } catch {\n findings.push(err(`${rel} is not valid JSON.`, 'Fix the syntax.', rel));\n continue;\n }\n const problems = validateAgainstSchema(operation.output, value);\n if (problems.length > 0) {\n findings.push(\n err(\n `${rel} violates the pinned output schema: ${problems[0]}`,\n 'A fixture must satisfy the contract, or the harness would show data the integration can never return.',\n rel,\n ),\n );\n }\n }\n }\n\n return findings;\n}\n\n// ─── manifest ───────────────────────────────────────────────────────────────\n\nexport function buildManifest(input: {\n project: ExperienceProject;\n definition: LoadedExperienceDefinition;\n pinned: readonly PinnedIntegration[];\n workflows: readonly WorkflowTemplate[];\n version: string;\n sdk: string;\n surfaces: ExperienceSurfaces;\n}): ExperienceManifest {\n const { project, definition, pinned } = input;\n const body = {\n schemaVersion: 1 as const,\n slug: project.slug,\n form: 'composed' as const,\n version: input.version,\n sdk: input.sdk,\n integrations: project.integrations,\n contractRefs: pinned.map(({ use, contract }) => ({\n integration: use.name,\n version: use.version,\n contractVersion: contract.contractVersion,\n digest: contract.digest,\n })),\n ...(definition.sidebar ? { sidebar: definition.sidebar } : {}),\n widgets: definition.widgets.map((w) => ({\n id: w.id,\n title: w.title,\n integrations: [...w.integrations],\n ...(w.width ? { width: w.width } : {}),\n ...(w.isCollapsible === undefined\n ? {}\n : { isCollapsible: w.isCollapsible }),\n ...(w.aiFooterEnabled === undefined\n ? {}\n : { aiFooterEnabled: w.aiFooterEnabled }),\n })),\n pages: definition.pages.map((p) => ({\n id: p.id,\n ...(p.path === undefined ? {} : { path: p.path }),\n title: p.title,\n integrations: [...(p.integrations ?? [])],\n ...(p.kind === undefined ? {} : { kind: p.kind }),\n ...(p.widgets === undefined ? {} : { widgets: [...p.widgets] }),\n ...(p.routes && p.routes.length > 0\n ? { routes: p.routes.map((r) => ({ path: r.path, title: r.title })) }\n : {}),\n })),\n surfacesDigest: input.surfaces.digest,\n workflowTemplates: [...input.workflows],\n ...(definition.reviewQueue\n ? {\n reviewQueue: {\n readsOnly: true as const,\n sections: definition.reviewQueue.sections.map((s) => ({\n id: s.id,\n integration: s.integration,\n read: s.read,\n })),\n },\n }\n : {}),\n };\n\n return {\n ...body,\n digest: `sha256:${sha256Hex(canonicalJson(body))}`,\n };\n}\n"]}
@@ -69,6 +69,8 @@ export interface LoadedExperienceDefinition {
69
69
  }
70
70
  export interface SerializedWorkflowOptions {
71
71
  effectOf: (integration: string, op: string) => 'read' | 'write' | undefined;
72
+ /** Read by SDK 0.22 and later; an older SDK ignores it and emits the placeholder installation id. */
73
+ experience?: string;
72
74
  }
73
75
  export interface LoadedExperienceModule {
74
76
  definition: LoadedExperienceDefinition;
@@ -1 +1 @@
1
- {"version":3,"file":"definition-shape.js","sourceRoot":"","sources":["../../src/experience/definition-shape.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * The structural slice of an `ExperienceDefinition` the CLI reads. The CLI does\n * not depend on `@ekanos/sdk`: the definition is produced by whichever SDK the\n * project installed, and anything the CLI needs computed (workflow\n * serialization) is obtained from that same SDK at load time.\n */\nexport interface LoadedWorkflowTemplate {\n id: string;\n name: string;\n build(): ReadonlyArray<{\n type: string;\n id: string;\n integration?: string;\n op?: string;\n }>;\n}\n\nexport interface LoadedExperienceDefinition {\n kind: 'experience';\n slug: string;\n name: string;\n description?: string;\n sidebar?: { section: string; icon: string; label: string };\n widgets: ReadonlyArray<{\n id: string;\n title: string;\n integrations: readonly string[];\n width?: string;\n isCollapsible?: boolean;\n isPinnable?: boolean;\n aiFooterEnabled?: boolean;\n }>;\n pages: ReadonlyArray<{\n id: string;\n /** The SDK sets it; a definition from before page kinds has none (custom). */\n kind?: 'overview' | 'canvas' | 'custom';\n path?: string;\n title: string;\n integrations?: readonly string[];\n widgets?: readonly string[];\n routes?: ReadonlyArray<{ path: string; title: string }>;\n }>;\n suggestedLayout?: {\n workspaces: ReadonlyArray<{\n slug: string;\n name: string;\n icon?: string;\n items: ReadonlyArray<{ ref: string; audiences?: readonly string[] }>;\n }>;\n };\n workflows: readonly LoadedWorkflowTemplate[];\n reviewQueue?: {\n readsOnly: true;\n sections: ReadonlyArray<{ id: string; integration: string; read: string }>;\n };\n}\n\nexport interface SerializedWorkflowOptions {\n effectOf: (integration: string, op: string) => 'read' | 'write' | undefined;\n}\n\nexport interface LoadedExperienceModule {\n definition: LoadedExperienceDefinition;\n /** The project's own SDK serializer, so the output matches the SDK that authored it. */\n serializeWorkflowTemplate(\n template: LoadedWorkflowTemplate,\n options: SerializedWorkflowOptions,\n ): unknown;\n slotsUsedBy(definition: LoadedExperienceDefinition): string[];\n}\n"]}
1
+ {"version":3,"file":"definition-shape.js","sourceRoot":"","sources":["../../src/experience/definition-shape.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * The structural slice of an `ExperienceDefinition` the CLI reads. The CLI does\n * not depend on `@ekanos/sdk`: the definition is produced by whichever SDK the\n * project installed, and anything the CLI needs computed (workflow\n * serialization) is obtained from that same SDK at load time.\n */\nexport interface LoadedWorkflowTemplate {\n id: string;\n name: string;\n build(): ReadonlyArray<{\n type: string;\n id: string;\n integration?: string;\n op?: string;\n }>;\n}\n\nexport interface LoadedExperienceDefinition {\n kind: 'experience';\n slug: string;\n name: string;\n description?: string;\n sidebar?: { section: string; icon: string; label: string };\n widgets: ReadonlyArray<{\n id: string;\n title: string;\n integrations: readonly string[];\n width?: string;\n isCollapsible?: boolean;\n isPinnable?: boolean;\n aiFooterEnabled?: boolean;\n }>;\n pages: ReadonlyArray<{\n id: string;\n /** The SDK sets it; a definition from before page kinds has none (custom). */\n kind?: 'overview' | 'canvas' | 'custom';\n path?: string;\n title: string;\n integrations?: readonly string[];\n widgets?: readonly string[];\n routes?: ReadonlyArray<{ path: string; title: string }>;\n }>;\n suggestedLayout?: {\n workspaces: ReadonlyArray<{\n slug: string;\n name: string;\n icon?: string;\n items: ReadonlyArray<{ ref: string; audiences?: readonly string[] }>;\n }>;\n };\n workflows: readonly LoadedWorkflowTemplate[];\n reviewQueue?: {\n readsOnly: true;\n sections: ReadonlyArray<{ id: string; integration: string; read: string }>;\n };\n}\n\nexport interface SerializedWorkflowOptions {\n effectOf: (integration: string, op: string) => 'read' | 'write' | undefined;\n /** Read by SDK 0.22 and later; an older SDK ignores it and emits the placeholder installation id. */\n experience?: string;\n}\n\nexport interface LoadedExperienceModule {\n definition: LoadedExperienceDefinition;\n /** The project's own SDK serializer, so the output matches the SDK that authored it. */\n serializeWorkflowTemplate(\n template: LoadedWorkflowTemplate,\n options: SerializedWorkflowOptions,\n ): unknown;\n slotsUsedBy(definition: LoadedExperienceDefinition): string[];\n}\n"]}
@@ -95,9 +95,15 @@ export function readExperienceProject(dir) {
95
95
  raw: record,
96
96
  };
97
97
  }
98
- /** Operations as canonical `<integration>@<version>/<kind>/<name>` ids, for lookups against a contract. */
98
+ /**
99
+ * Operations as canonical `<slug>@<version>/<kind>/<name>` ids, for lookups
100
+ * against a contract. A contract's ids carry the bare slug even when the
101
+ * package is named under a namespace, so a `vastly/news` entry canonicalises to
102
+ * `news@0.1/...`.
103
+ */
99
104
  function withCanonicalOperations(entry) {
100
- return Object.assign(Object.assign({}, entry), { operations: entry.operations.map((id) => canonicalOperationId(entry, id)) });
105
+ const slug = entry.name.slice(entry.name.indexOf('/') + 1);
106
+ return Object.assign(Object.assign({}, entry), { operations: entry.operations.map((id) => canonicalOperationId({ name: slug, version: entry.version }, id)) });
101
107
  }
102
108
  /** 2-space JSON with a trailing newline: the format every written file uses. */
103
109
  export function formatJson(value) {