@noodleseed/one 0.177.0 → 0.179.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 (74) hide show
  1. package/dist/commands/solutions-activity.d.ts.map +1 -1
  2. package/dist/commands/solutions-activity.js +9 -35
  3. package/dist/commands/solutions-activity.js.map +1 -1
  4. package/dist/commands/solutions-conversations.d.ts.map +1 -1
  5. package/dist/commands/solutions-conversations.js +65 -6
  6. package/dist/commands/solutions-conversations.js.map +1 -1
  7. package/dist/commands/solutions-history.d.ts +9 -0
  8. package/dist/commands/solutions-history.d.ts.map +1 -0
  9. package/dist/commands/solutions-history.js +166 -0
  10. package/dist/commands/solutions-history.js.map +1 -0
  11. package/dist/commands/solutions-ops.d.ts.map +1 -1
  12. package/dist/commands/solutions-ops.js +3 -0
  13. package/dist/commands/solutions-ops.js.map +1 -1
  14. package/dist/commands/whatsapp-ops.d.ts.map +1 -1
  15. package/dist/commands/whatsapp-ops.js +0 -7
  16. package/dist/commands/whatsapp-ops.js.map +1 -1
  17. package/node_modules/@noodle-borg/agent-kit/dist/generated/example-files.js +1 -1
  18. package/node_modules/@noodle-borg/agent-kit/dist/skill-embedded-assistant-ref.js +14 -0
  19. package/node_modules/@noodle-borg/agent-kit/package.json +1 -1
  20. package/node_modules/@noodle-borg/assistant-gateway/dist/public-surface.d.ts +6 -0
  21. package/node_modules/@noodle-borg/assistant-gateway/dist/public-surface.js +5 -2
  22. package/node_modules/@noodle-borg/assistant-gateway/package.json +1 -1
  23. package/node_modules/@noodle-borg/authoring/dist/assistant.d.ts +18 -0
  24. package/node_modules/@noodle-borg/authoring/dist/assistant.js +14 -1
  25. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-channels.js +0 -3
  26. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-solution-conversations.js +50 -5
  27. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-solution-history.js +82 -0
  28. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-solutions.js +3 -42
  29. package/node_modules/@noodle-borg/compiler/dist/manifest/schema.d.ts +8 -0
  30. package/node_modules/@noodle-borg/compiler/dist/manifest/schema.js +7 -0
  31. package/node_modules/@noodle-borg/service/dist/application-activity.js +76 -21
  32. package/node_modules/@noodle-borg/service/dist/application-history-settings.js +108 -0
  33. package/node_modules/@noodle-borg/service/dist/assistant-composition.js +11 -2
  34. package/node_modules/@noodle-borg/service/dist/business-information/contracts.d.ts +3 -1
  35. package/node_modules/@noodle-borg/service/dist/business-information/workspace-permissions.js +1 -0
  36. package/node_modules/@noodle-borg/service/dist/channels/composition.js +10 -1
  37. package/node_modules/@noodle-borg/service/dist/channels/provider.js +13 -13
  38. package/node_modules/@noodle-borg/service/dist/channels/runtime.js +31 -5
  39. package/node_modules/@noodle-borg/service/dist/conversation-history/capture.js +63 -7
  40. package/node_modules/@noodle-borg/service/dist/conversation-history/contracts.js +13 -0
  41. package/node_modules/@noodle-borg/service/dist/conversation-history/customer.js +118 -0
  42. package/node_modules/@noodle-borg/service/dist/conversation-history/operator.js +147 -24
  43. package/node_modules/@noodle-borg/service/dist/conversation-history/preview.js +43 -0
  44. package/node_modules/@noodle-borg/service/dist/routes/assistant-conversations.js +52 -0
  45. package/node_modules/@noodle-borg/service/dist/routes/assistant-dispatch.js +6 -0
  46. package/node_modules/@noodle-borg/service/dist/routes/assistant-elevation.js +3 -0
  47. package/node_modules/@noodle-borg/service/dist/routes/assistant-interaction-stream.js +2 -1
  48. package/node_modules/@noodle-borg/service/dist/routes/assistant-interactions.js +6 -11
  49. package/node_modules/@noodle-borg/service/dist/routes/assistant-public-session.js +6 -0
  50. package/node_modules/@noodle-borg/service/dist/routes/assistant-route-http.js +16 -0
  51. package/node_modules/@noodle-borg/service/dist/routes/assistant.js +5 -17
  52. package/node_modules/@noodle-borg/service/dist/routes/business-information-activity.js +6 -5
  53. package/node_modules/@noodle-borg/service/dist/routes/business-information-conversations.js +67 -13
  54. package/node_modules/@noodle-borg/service/dist/routes/business-information-dispatch.js +4 -2
  55. package/node_modules/@noodle-borg/service/dist/routes/business-information-paths.js +4 -2
  56. package/node_modules/@noodle-borg/service/dist/routes/business-information.js +4 -0
  57. package/node_modules/@noodle-borg/service/dist/routes/whatsapp.js +0 -10
  58. package/node_modules/@noodle-borg/service/dist/service-history-projections.js +35 -4
  59. package/node_modules/@noodle-borg/service/dist/service-resource-cleanup.js +32 -0
  60. package/node_modules/@noodle-borg/service/dist/service.js +4 -3
  61. package/node_modules/@noodle-borg/service/package.json +1 -1
  62. package/node_modules/@noodle-borg/wire-contracts/dist/application-activity.d.ts +0 -28
  63. package/node_modules/@noodle-borg/wire-contracts/dist/application-activity.js +0 -18
  64. package/node_modules/@noodle-borg/wire-contracts/dist/application-history-settings.d.ts +190 -0
  65. package/node_modules/@noodle-borg/wire-contracts/dist/application-history-settings.js +92 -0
  66. package/node_modules/@noodle-borg/wire-contracts/dist/assistant.d.ts +3 -0
  67. package/node_modules/@noodle-borg/wire-contracts/dist/assistant.js +6 -0
  68. package/node_modules/@noodle-borg/wire-contracts/dist/conversation-history.d.ts +182 -0
  69. package/node_modules/@noodle-borg/wire-contracts/dist/conversation-history.js +78 -2
  70. package/node_modules/@noodle-borg/wire-contracts/dist/index.d.ts +1 -0
  71. package/node_modules/@noodle-borg/wire-contracts/dist/index.js +1 -0
  72. package/node_modules/@noodleseed/assistant/README.md +19 -0
  73. package/node_modules/@noodleseed/assistant/package.json +1 -1
  74. package/package.json +2 -2
@@ -1,25 +1,45 @@
1
1
  import { readJsonBody, sendJson } from '@noodle-borg/transport-http';
2
+ import { ConversationReviewRequestSchema } from '@noodle-borg/wire-contracts';
3
+ import { businessGrantAllows } from '../business-information/model.js';
2
4
  import { ConversationHistoryError, } from '../conversation-history/operator.js';
5
+ import { sendForbidden } from '../http-util.js';
3
6
  import { requireIdentity, requireInstallationPermission, } from './business-information.js';
4
- /** ADR 0241 decision 10: readers see text; only export and erasure need Owner/Administrator authority. */
7
+ import { resolveBusinessStaffGrant } from './business-information-access.js';
8
+ /**
9
+ * ADR 0241 decision 10: readers see text; reviewing and noting need the record-handling permissions an
10
+ * Operator holds; only export and erasure need Owner/Administrator authority.
11
+ */
5
12
  const PERMISSIONS = {
6
13
  list: 'records:read',
7
14
  show: 'records:read',
8
15
  export: 'records:export',
9
16
  forget: 'records:delete',
10
17
  };
18
+ const METHODS = { list: ['GET'], show: ['GET', 'PATCH'], export: ['GET'], forget: ['POST'] };
11
19
  export async function handleApplicationConversations(req, res, url, ref, deps) {
12
- const action = ref.conversationAction ?? 'list';
13
- const method = action === 'forget' ? 'POST' : 'GET';
14
- if (req.method !== method) {
15
- res.setHeader('allow', method);
20
+ const route = ref.conversationAction ?? 'list';
21
+ const methods = METHODS[route];
22
+ if (!methods.includes(req.method ?? '')) {
23
+ res.setHeader('allow', methods.join(', '));
16
24
  return sendJson(res, 405, { error: 'method not allowed' });
17
25
  }
26
+ const action = req.method === 'PATCH' ? 'review' : route;
18
27
  const identity = await requireIdentity(req, res, deps);
19
28
  if (identity === false)
20
29
  return;
21
- const permission = PERMISSIONS[action];
22
- const authorize = () => requireInstallationPermission(res, ref, identity, permission, deps);
30
+ // A review's permissions follow its fields, so it is read-authorized before its body is parsed.
31
+ let permissions = [
32
+ action === 'list' || action === 'show'
33
+ ? await readPermission(ref, identity, deps)
34
+ : PERMISSIONS[route],
35
+ ];
36
+ const authorize = async () => {
37
+ const [last = PERMISSIONS[route], ...earlier] = [...permissions].reverse();
38
+ for (const permission of earlier)
39
+ if (!(await requireInstallationPermission(res, ref, identity, permission, deps)))
40
+ return false;
41
+ return requireInstallationPermission(res, ref, identity, last, deps);
42
+ };
23
43
  const authorized = await authorize();
24
44
  if (!authorized)
25
45
  return;
@@ -28,29 +48,45 @@ export async function handleApplicationConversations(req, res, url, ref, deps) {
28
48
  if (!deps.conversations)
29
49
  throw new ConversationHistoryError('conversation_unavailable');
30
50
  let body;
31
- if (method === 'POST') {
51
+ if (req.method !== 'GET') {
32
52
  const parsed = await readJsonBody(req, deps.maxBody);
33
53
  if (!parsed.ok)
34
54
  return sendJson(res, parsed.status, { error: parsed.error });
35
55
  body = parsed.value;
56
+ if (action === 'review') {
57
+ const review = ConversationReviewRequestSchema.safeParse(body);
58
+ if (!review.success)
59
+ throw new ConversationHistoryError('conversation_invalid');
60
+ permissions = [
61
+ ...(review.data.reviewStatus === undefined ? [] : ['records:status']),
62
+ ...(review.data.note === undefined ? [] : ['records:note']),
63
+ ];
64
+ }
36
65
  if (!(await authorize()))
37
66
  return;
38
67
  }
68
+ const fence = permissions.at(-1) ?? PERMISSIONS[route];
39
69
  const result = await deps.conversations.project(authorized.scope, action, {
40
70
  parameters: [...url.searchParams.entries()],
41
71
  ...(ref.conversationId === undefined ? {} : { conversationId: ref.conversationId }),
42
72
  body,
43
- }, (operation) => deps.store.staff.run(authorized.scope, identity.subject, permission, operation));
44
- if ('audit' in result && result.audit)
73
+ actor: identity.subject,
74
+ ...(deps.forgetWhatsApp ? { forgetWorkingMemory: deps.forgetWhatsApp } : {}),
75
+ }, (operation) => deps.store.staff.run(authorized.scope, identity.subject, fence, operation));
76
+ for (const event of result.audits)
45
77
  await deps.audit?.emit({
46
- ...result.audit,
78
+ ...event,
47
79
  org: ref.org,
48
80
  app: authorized.scope.app,
49
81
  env: authorized.scope.env,
50
82
  actorSubject: identity.subject,
51
83
  });
52
- if (await authorize())
53
- sendJson(res, 200, result.response);
84
+ if (!(await authorize()))
85
+ return;
86
+ // A Preview read is answered only while the environment is still a Preview.
87
+ if (fence === 'drafts:preview' && !(await deps.conversations.isPreview(authorized.scope)))
88
+ return sendForbidden(res, 'business permission required: records:read');
89
+ sendJson(res, 200, result.response);
54
90
  }
55
91
  catch (error) {
56
92
  if (!(error instanceof ConversationHistoryError))
@@ -62,4 +98,22 @@ export async function handleApplicationConversations(req, res, url, ref, deps) {
62
98
  : 400, { code: error.code, error: error.message });
63
99
  }
64
100
  }
101
+ /**
102
+ * ADR 0241 decision 18: a Builder never holds `records:read`, but reads a Preview environment's
103
+ * conversations under `drafts:preview`. Every other caller keeps the ordinary read permission, so a
104
+ * production installation still denies Builders.
105
+ */
106
+ async function readPermission(ref, identity, deps) {
107
+ if (ref.installationId === undefined || !deps.conversations)
108
+ return 'records:read';
109
+ const installation = await deps.store.getInstallationById(ref.org, ref.installationId);
110
+ if (installation === undefined)
111
+ return 'records:read';
112
+ const grant = await resolveBusinessStaffGrant(deps, installation.scope, identity.subject);
113
+ return !businessGrantAllows(grant, 'records:read') &&
114
+ businessGrantAllows(grant, 'drafts:preview') &&
115
+ (await deps.conversations.isPreview(installation.scope))
116
+ ? 'drafts:preview'
117
+ : 'records:read';
118
+ }
65
119
  //# sourceMappingURL=business-information-conversations.js.map
@@ -9,7 +9,7 @@ import { SourceCapacityError } from '../business-information/source-custody-budg
9
9
  import { BusinessWorkspaceError } from '../business-workspaces/contracts.js';
10
10
  import { respondRouteError } from '../http-util.js';
11
11
  import { handleBusinessGrants, handleManagedRecords, handleSolutionCatalog, handleSolutionInstallations, } from './business-information.js';
12
- import { handleApplicationActivity, } from './business-information-activity.js';
12
+ import { handleApplicationActivity } from './business-information-activity.js';
13
13
  import { handleBusinessChannels, } from './business-information-channels.js';
14
14
  import { handleApplicationConnectionCallback, handleApplicationConnections, } from './business-information-connections.js';
15
15
  import { handleApplicationConversations, } from './business-information-conversations.js';
@@ -79,7 +79,9 @@ export function dispatchBusinessInformationRoutes(req, res, url, deps) {
79
79
  return run(req, res, deps, () => handleNativeRecordLifecycle(req, res, installationRef, deps));
80
80
  if (installationRef.action === 'notice')
81
81
  return run(req, res, deps, () => handleBusinessNotice(req, res, installationRef, deps));
82
- if ((installationRef.action === 'activity' || installationRef.action === 'coordination') &&
82
+ if ((installationRef.action === 'activity' ||
83
+ installationRef.action === 'history' ||
84
+ installationRef.action === 'coordination') &&
83
85
  installationRef.collection === undefined)
84
86
  return run(req, res, deps, () => handleApplicationActivity(req, res, url, installationRef, deps));
85
87
  if (installationRef.action === 'conversations')
@@ -43,7 +43,7 @@ export function parseSolutionInstallationPath(pathname) {
43
43
  : { conversationAction: 'show', conversationId: segment }),
44
44
  };
45
45
  }
46
- const application = /^\/v1\/orgs\/([^/]+)\/solution-installations\/([^/]+)\/(activate|settings|notice|record-lifecycle|channels|operations\/coordination(?:\/resolve)?|activity(?:\/(?:settings|export|preview))?)$/.exec(pathname);
46
+ const application = /^\/v1\/orgs\/([^/]+)\/solution-installations\/([^/]+)\/(activate|settings|notice|record-lifecycle|channels|operations\/coordination(?:\/resolve)?|history\/settings|activity(?:\/(?:export|preview))?)$/.exec(pathname);
47
47
  if (application !== null) {
48
48
  const org = decoded(application, 1);
49
49
  const installationId = decoded(application, 2);
@@ -56,7 +56,9 @@ export function parseSolutionInstallationPath(pathname) {
56
56
  ? 'coordination'
57
57
  : application[3]?.startsWith('activity')
58
58
  ? 'activity'
59
- : application[3],
59
+ : application[3] === 'history/settings'
60
+ ? 'history'
61
+ : application[3],
60
62
  };
61
63
  }
62
64
  let match = /^\/v1\/orgs\/([^/]+)\/solution-installations$/.exec(pathname);
@@ -68,6 +68,10 @@ export async function handleSolutionInstallations(req, res, ref, deps) {
68
68
  code: 'installation_conflict',
69
69
  });
70
70
  }
71
+ // Only a created installation opts in (ADR 0241 decision 8), before activation can read the setting.
72
+ // Without a verified allowance it stays not enabled: recording nothing is the safe failure.
73
+ if (result.disposition === 'created')
74
+ await deps.activity?.initializeHistory(result.installation.scope).catch(() => false);
71
75
  const grant = await resolveBusinessStaffGrant(deps, result.installation.scope, identity.subject);
72
76
  if (grant === undefined || grant.revokedAt !== undefined) {
73
77
  return sendForbidden(res, 'business grant required');
@@ -209,16 +209,6 @@ async function operate(req, res, url, tenant, path, runtime, grants) {
209
209
  }
210
210
  return respond(res, wire.WhatsAppCooldownResponseSchema, await channels.cooldown(id, value));
211
211
  }
212
- if (kind === 'participants' &&
213
- value &&
214
- participant.test(value) &&
215
- action === 'forget' &&
216
- req.method === 'POST') {
217
- await body(req, wire.WhatsAppEmptyRequestSchema);
218
- await channels.forget(id, value, identity.subject, idempotency);
219
- await audit('conversation_forgotten');
220
- return sendJson(res, 200, { ok: true });
221
- }
222
212
  if (kind === 'events' &&
223
213
  (!value || eventId.test(value)) &&
224
214
  (read || (action === 'reconcile' && req.method === 'POST'))) {
@@ -1,24 +1,55 @@
1
1
  import { randomBytes } from 'node:crypto';
2
- import { ApplicationActivity } from './application-activity.js';
2
+ import { ActivityPolicyError, ApplicationActivity } from './application-activity.js';
3
+ import { historyDisabledSurfaces } from './application-history-settings.js';
3
4
  import { ApplicationConversations } from './conversation-history/operator.js';
5
+ import { previewEnvironments, withPreviewConversations } from './conversation-history/preview.js';
4
6
  /** Installation history projections over the optional durable stores the service was given. */
5
- export function createHistoryProjections(options, moduleHost) {
7
+ export function createHistoryProjections(options, moduleHost, installations, registry) {
8
+ const history = options.conversationHistory;
6
9
  const activity = options.operationEvidence === undefined
7
10
  ? undefined
8
11
  : new ApplicationActivity({
9
12
  ...options.operationEvidence,
10
13
  allowance: async (org, request) => moduleHost.resolveActivityHistoryAllowance?.(org, request),
14
+ ...(history === undefined ? {} : { conversationHistory: history.store }),
15
+ historyDisabledSurfaces: async (scope) => historyDisabledSurfaces((await registry.getActiveByTenant(scope))?.served.artifact.server.assistant),
11
16
  });
12
- const history = options.conversationHistory;
17
+ const preview = previewEnvironments(registry);
18
+ const conversationPolicy = withPreviewConversations(history?.policy ?? settingsConversationPolicy(installations, activity), preview);
13
19
  const conversations = history === undefined
14
20
  ? undefined
15
21
  : new ApplicationConversations({
16
22
  store: history.store,
23
+ policy: conversationPolicy,
24
+ preview,
17
25
  identityKey: history.identityKey ?? randomBytes(32).toString('hex'),
18
26
  ...(options.clock === undefined
19
27
  ? {}
20
28
  : { now: () => options.clock?.().getTime() ?? Date.now() }),
21
29
  });
22
- return { activity, conversations };
30
+ return { activity, conversations, conversationPolicy };
31
+ }
32
+ /**
33
+ * Capture follows the installation history setting under the live plan allowance (ADR 0241). A tenant
34
+ * with no single installation, setting opt-in or verified allowance records nothing, and the read never
35
+ * creates a setting.
36
+ */
37
+ function settingsConversationPolicy(installations, activity) {
38
+ return async (tenant) => {
39
+ if (!installations || !activity)
40
+ return undefined;
41
+ const matching = (await installations.listInstallations(tenant.org)).filter((item) => item.scope.app === tenant.app && item.scope.env === tenant.env);
42
+ const installation = matching.length === 1 ? matching[0] : undefined;
43
+ if (!installation)
44
+ return undefined;
45
+ try {
46
+ return await activity.conversationPolicy(installation.scope);
47
+ }
48
+ catch (error) {
49
+ if (error instanceof ActivityPolicyError)
50
+ return undefined;
51
+ throw error;
52
+ }
53
+ };
23
54
  }
24
55
  //# sourceMappingURL=service-history-projections.js.map
@@ -24,6 +24,38 @@ export async function closeServiceResources(input) {
24
24
  if (errors.length > 0)
25
25
  throw new AggregateError(errors, 'service resource cleanup failed');
26
26
  }
27
+ /**
28
+ * Clean up after a failed boot without letting a cleanup failure replace the error that aborted startup:
29
+ * operators must see the bind or boot cause, while the cleanup failure is still logged.
30
+ */
31
+ export async function cleanupAfterStartupFailure(logger, phase, cleanup) {
32
+ try {
33
+ await cleanup();
34
+ }
35
+ catch (error) {
36
+ const code = firstErrorCode(error);
37
+ logger.error('service.startup_cleanup_failed', {
38
+ phase,
39
+ name: error instanceof Error ? error.name : 'unknown',
40
+ ...(code === undefined ? {} : { code }),
41
+ });
42
+ }
43
+ }
44
+ /** The first scalar driver/system code, searching nested cleanup aggregates depth-first. */
45
+ function firstErrorCode(error, depth = 0) {
46
+ if (typeof error !== 'object' || error === null || depth > 4)
47
+ return undefined;
48
+ if ('code' in error && typeof error.code === 'string')
49
+ return error.code;
50
+ if (!(error instanceof AggregateError))
51
+ return undefined;
52
+ for (const nested of error.errors) {
53
+ const code = firstErrorCode(nested, depth + 1);
54
+ if (code !== undefined)
55
+ return code;
56
+ }
57
+ return undefined;
58
+ }
27
59
  export function listenHttpServer(http, port, host) {
28
60
  return new Promise((resolve, reject) => {
29
61
  const onError = (error) => {
@@ -14,7 +14,7 @@ import { assistantRouteDependencies } from './assistant-composition.js';
14
14
  import { resolveBuildInfo } from './build-info.js';
15
15
  import { createBusinessInformationRuntime, resolvePrivateInstallationDefinition, } from './business-information-runtime.js';
16
16
  import { serviceCapabilityReport } from './capabilities.js';
17
- import { createWhatsAppRuntime } from './channels/composition.js';
17
+ import { createWhatsAppRuntime, whatsappBusinessRoutes } from './channels/composition.js';
18
18
  import { rejectIncompatibleCli } from './client-compatibility.js';
19
19
  import { createDataPlaneMembershipAuthorizer } from './data-plane-membership.js';
20
20
  import { DEVELOPER_MCP_PATH, handleDeveloperMcpRequest } from './developer-mcp/mount.js';
@@ -95,7 +95,7 @@ export function createServiceHandler(registry, options = {}) {
95
95
  activeAudit = audit;
96
96
  const { publicTenantRouting } = mcp.mcpRoutingOptions(options, controlPlane);
97
97
  const resolveEndpointOptions = (org) => mcp.endpointUrlOptionsForOrg(options, controlPlane, org);
98
- const { activity, conversations } = createHistoryProjections(options, moduleHost);
98
+ const { activity, conversations, conversationPolicy } = createHistoryProjections(options, moduleHost, businessInformationStore, registry);
99
99
  const withIntentMode = createIntentTargetResolver(intentSettings, intentPreviewOrgs);
100
100
  const { activateInstallation, readInstallationActivation, resolveRuntimeTarget, businessOnboarding, } = createApplicationServingRuntime(registry, providerOptions, controlPlane, audit, activity);
101
101
  const runtimeTarget = async (target) => target === undefined ? undefined : resolveRuntimeTarget(target);
@@ -192,6 +192,7 @@ export function createServiceHandler(registry, options = {}) {
192
192
  maxBody,
193
193
  serviceBase: (request) => options.publicBaseUrl ?? baseFromRequest(request, tls),
194
194
  logger,
195
+ conversationPolicy,
195
196
  });
196
197
  const whatsapp = createWhatsAppRuntime(options.whatsapp, assistantDeps, {
197
198
  allowance: moduleHost.resolveActivityHistoryAllowance,
@@ -302,7 +303,7 @@ export function createServiceHandler(registry, options = {}) {
302
303
  dispatchBusinessInformationRoutes(req, res, url, {
303
304
  pageOrigin: options.businessPageOrigin,
304
305
  pageServiceUrl: options.publicBaseUrl,
305
- ...(whatsapp ? { readWhatsApp: whatsapp.projection.bind(whatsapp) } : {}),
306
+ ...whatsappBusinessRoutes(whatsapp),
306
307
  store: businessInformationStore,
307
308
  ...(options.businessAuthoring ? { workspaces: options.businessAuthoring.workspaces } : {}),
308
309
  ...(businessOnboarding ? { businessOnboarding } : {}),
@@ -41,7 +41,7 @@
41
41
  "@noodle-borg/managed-capabilities": "0.0.0",
42
42
  "@modelcontextprotocol/sdk": "^1.29.0",
43
43
  "@noodle-borg/admission-limits": "0.0.0",
44
- "@noodle-borg/agent-kit": "0.107.0",
44
+ "@noodle-borg/agent-kit": "0.108.0",
45
45
  "@noodle-borg/app-package": "0.0.0",
46
46
  "@noodle-borg/assistant-gateway": "0.0.0",
47
47
  "@noodle-borg/auth": "0.0.0",
@@ -42,25 +42,6 @@ export declare const ApplicationActivityListResponseSchema: z.ZodObject<{
42
42
  historyDays: z.ZodNumber;
43
43
  }, z.core.$strict>;
44
44
  }, z.core.$strict>;
45
- export declare const ApplicationActivitySettingsSchema: z.ZodObject<{
46
- revision: z.ZodString;
47
- retentionDays: z.ZodNumber;
48
- maximumDays: z.ZodNumber;
49
- canEdit: z.ZodBoolean;
50
- }, z.core.$strict>;
51
- export declare const ApplicationActivitySettingsResponseSchema: z.ZodObject<{
52
- ok: z.ZodLiteral<true>;
53
- data: z.ZodObject<{
54
- revision: z.ZodString;
55
- retentionDays: z.ZodNumber;
56
- maximumDays: z.ZodNumber;
57
- canEdit: z.ZodBoolean;
58
- }, z.core.$strict>;
59
- }, z.core.$strict>;
60
- export declare const ApplicationActivitySettingsSaveRequestSchema: z.ZodObject<{
61
- expectedRevision: z.ZodString;
62
- retentionDays: z.ZodNumber;
63
- }, z.core.$strict>;
64
45
  /** Clients tolerate additive response fields; writes and server output remain strict. */
65
46
  export declare const ApplicationActivityListClientResponseSchema: z.ZodObject<{
66
47
  ok: z.ZodLiteral<true>;
@@ -87,15 +68,6 @@ export declare const ApplicationActivityListClientResponseSchema: z.ZodObject<{
87
68
  historyDays: z.ZodNumber;
88
69
  }, z.core.$strip>;
89
70
  }, z.core.$strip>;
90
- export declare const ApplicationActivitySettingsClientResponseSchema: z.ZodObject<{
91
- ok: z.ZodLiteral<true>;
92
- data: z.ZodObject<{
93
- revision: z.ZodString;
94
- retentionDays: z.ZodNumber;
95
- maximumDays: z.ZodNumber;
96
- canEdit: z.ZodBoolean;
97
- }, z.core.$strip>;
98
- }, z.core.$strip>;
99
71
  export declare const ApplicationActivityPreviewResponseSchema: z.ZodObject<{
100
72
  ok: z.ZodLiteral<true>;
101
73
  data: z.ZodDiscriminatedUnion<[z.ZodObject<{
@@ -18,20 +18,6 @@ export const ApplicationActivityListResponseSchema = z.strictObject({
18
18
  historyDays: z.number().int().min(1).max(365),
19
19
  }),
20
20
  });
21
- export const ApplicationActivitySettingsSchema = z.strictObject({
22
- revision: z.string().regex(/^[a-f0-9]{64}$/),
23
- retentionDays: z.number().int().min(1).max(365),
24
- maximumDays: z.number().int().min(1).max(365),
25
- canEdit: z.boolean(),
26
- });
27
- export const ApplicationActivitySettingsResponseSchema = z.strictObject({
28
- ok: z.literal(true),
29
- data: ApplicationActivitySettingsSchema,
30
- });
31
- export const ApplicationActivitySettingsSaveRequestSchema = z.strictObject({
32
- expectedRevision: z.string().regex(/^[a-f0-9]{64}$/),
33
- retentionDays: z.number().int().min(1).max(365),
34
- });
35
21
  /** Clients tolerate additive response fields; writes and server output remain strict. */
36
22
  export const ApplicationActivityListClientResponseSchema = z.object({
37
23
  ok: z.literal(true),
@@ -45,10 +31,6 @@ export const ApplicationActivityListClientResponseSchema = z.object({
45
31
  .max(100),
46
32
  }),
47
33
  });
48
- export const ApplicationActivitySettingsClientResponseSchema = z.object({
49
- ok: z.literal(true),
50
- data: z.object(ApplicationActivitySettingsSchema.shape),
51
- });
52
34
  const ActivityPreviewScenarioSchema = z.strictObject({
53
35
  id: z.string().min(1).max(128),
54
36
  label: z.string().min(1).max(128),
@@ -0,0 +1,190 @@
1
+ import { z } from 'zod';
2
+ export declare const HistorySourcesSchema: z.ZodObject<{
3
+ websiteVisitors: z.ZodBoolean;
4
+ signedInCustomers: z.ZodBoolean;
5
+ whatsapp: z.ZodBoolean;
6
+ }, z.core.$strict>;
7
+ /** A surface the application declared `history: false` on, named by its authoring constructor. */
8
+ export declare const ApplicationHistoryDisabledSurfaceSchema: z.ZodEnum<{
9
+ publicWebsite: "publicWebsite";
10
+ authenticatedWebsite: "authenticatedWebsite";
11
+ publicMessaging: "publicMessaging";
12
+ }>;
13
+ export declare const ApplicationHistorySettingsSchema: z.ZodObject<{
14
+ revision: z.ZodString;
15
+ canEdit: z.ZodBoolean;
16
+ activity: z.ZodObject<{
17
+ retentionDays: z.ZodNumber;
18
+ maximumDays: z.ZodNumber;
19
+ defaultDays: z.ZodNumber;
20
+ }, z.core.$strict>;
21
+ conversations: z.ZodObject<{
22
+ state: z.ZodEnum<{
23
+ not_enabled: "not_enabled";
24
+ off: "off";
25
+ on: "on";
26
+ }>;
27
+ retentionDays: z.ZodOptional<z.ZodNumber>;
28
+ sources: z.ZodObject<{
29
+ websiteVisitors: z.ZodBoolean;
30
+ signedInCustomers: z.ZodBoolean;
31
+ whatsapp: z.ZodBoolean;
32
+ }, z.core.$strict>;
33
+ disabledByApplication: z.ZodOptional<z.ZodArray<z.ZodEnum<{
34
+ publicWebsite: "publicWebsite";
35
+ authenticatedWebsite: "authenticatedWebsite";
36
+ publicMessaging: "publicMessaging";
37
+ }>>>;
38
+ }, z.core.$strict>;
39
+ }, z.core.$strict>;
40
+ export declare const ApplicationHistorySettingsResponseSchema: z.ZodObject<{
41
+ ok: z.ZodLiteral<true>;
42
+ data: z.ZodObject<{
43
+ revision: z.ZodString;
44
+ canEdit: z.ZodBoolean;
45
+ activity: z.ZodObject<{
46
+ retentionDays: z.ZodNumber;
47
+ maximumDays: z.ZodNumber;
48
+ defaultDays: z.ZodNumber;
49
+ }, z.core.$strict>;
50
+ conversations: z.ZodObject<{
51
+ state: z.ZodEnum<{
52
+ not_enabled: "not_enabled";
53
+ off: "off";
54
+ on: "on";
55
+ }>;
56
+ retentionDays: z.ZodOptional<z.ZodNumber>;
57
+ sources: z.ZodObject<{
58
+ websiteVisitors: z.ZodBoolean;
59
+ signedInCustomers: z.ZodBoolean;
60
+ whatsapp: z.ZodBoolean;
61
+ }, z.core.$strict>;
62
+ disabledByApplication: z.ZodOptional<z.ZodArray<z.ZodEnum<{
63
+ publicWebsite: "publicWebsite";
64
+ authenticatedWebsite: "authenticatedWebsite";
65
+ publicMessaging: "publicMessaging";
66
+ }>>>;
67
+ }, z.core.$strict>;
68
+ }, z.core.$strict>;
69
+ }, z.core.$strict>;
70
+ /** Omitted fields keep their value; `dryRun` reports the effect without saving. */
71
+ export declare const ApplicationHistorySettingsSaveRequestSchema: z.ZodObject<{
72
+ expectedRevision: z.ZodString;
73
+ activityDays: z.ZodOptional<z.ZodNumber>;
74
+ conversations: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
75
+ retentionDays: z.ZodNumber;
76
+ }, z.core.$strict>, z.ZodLiteral<"off">]>>;
77
+ sources: z.ZodOptional<z.ZodObject<{
78
+ websiteVisitors: z.ZodOptional<z.ZodBoolean>;
79
+ signedInCustomers: z.ZodOptional<z.ZodBoolean>;
80
+ whatsapp: z.ZodOptional<z.ZodBoolean>;
81
+ }, z.core.$strict>>;
82
+ dryRun: z.ZodOptional<z.ZodBoolean>;
83
+ }, z.core.$strict>;
84
+ export declare const ApplicationHistorySettingsSaveResponseSchema: z.ZodObject<{
85
+ ok: z.ZodLiteral<true>;
86
+ data: z.ZodObject<{
87
+ dryRun: z.ZodBoolean;
88
+ shortensConversations: z.ZodBoolean;
89
+ impact: z.ZodObject<{
90
+ conversations: z.ZodNumber;
91
+ items: z.ZodNumber;
92
+ }, z.core.$strict>;
93
+ settings: z.ZodObject<{
94
+ revision: z.ZodString;
95
+ canEdit: z.ZodBoolean;
96
+ activity: z.ZodObject<{
97
+ retentionDays: z.ZodNumber;
98
+ maximumDays: z.ZodNumber;
99
+ defaultDays: z.ZodNumber;
100
+ }, z.core.$strict>;
101
+ conversations: z.ZodObject<{
102
+ state: z.ZodEnum<{
103
+ not_enabled: "not_enabled";
104
+ off: "off";
105
+ on: "on";
106
+ }>;
107
+ retentionDays: z.ZodOptional<z.ZodNumber>;
108
+ sources: z.ZodObject<{
109
+ websiteVisitors: z.ZodBoolean;
110
+ signedInCustomers: z.ZodBoolean;
111
+ whatsapp: z.ZodBoolean;
112
+ }, z.core.$strict>;
113
+ disabledByApplication: z.ZodOptional<z.ZodArray<z.ZodEnum<{
114
+ publicWebsite: "publicWebsite";
115
+ authenticatedWebsite: "authenticatedWebsite";
116
+ publicMessaging: "publicMessaging";
117
+ }>>>;
118
+ }, z.core.$strict>;
119
+ }, z.core.$strict>;
120
+ }, z.core.$strict>;
121
+ }, z.core.$strict>;
122
+ export declare const ApplicationHistorySettingsClientResponseSchema: z.ZodObject<{
123
+ ok: z.ZodLiteral<true>;
124
+ data: z.ZodObject<{
125
+ activity: z.ZodObject<{
126
+ retentionDays: z.ZodNumber;
127
+ maximumDays: z.ZodNumber;
128
+ defaultDays: z.ZodNumber;
129
+ }, z.core.$strip>;
130
+ conversations: z.ZodObject<{
131
+ sources: z.ZodObject<{
132
+ websiteVisitors: z.ZodBoolean;
133
+ signedInCustomers: z.ZodBoolean;
134
+ whatsapp: z.ZodBoolean;
135
+ }, z.core.$strip>;
136
+ state: z.ZodEnum<{
137
+ not_enabled: "not_enabled";
138
+ off: "off";
139
+ on: "on";
140
+ }>;
141
+ retentionDays: z.ZodOptional<z.ZodNumber>;
142
+ disabledByApplication: z.ZodOptional<z.ZodArray<z.ZodEnum<{
143
+ publicWebsite: "publicWebsite";
144
+ authenticatedWebsite: "authenticatedWebsite";
145
+ publicMessaging: "publicMessaging";
146
+ }>>>;
147
+ }, z.core.$strip>;
148
+ revision: z.ZodString;
149
+ canEdit: z.ZodBoolean;
150
+ }, z.core.$strip>;
151
+ }, z.core.$strip>;
152
+ export declare const ApplicationHistorySettingsSaveClientResponseSchema: z.ZodObject<{
153
+ ok: z.ZodLiteral<true>;
154
+ data: z.ZodObject<{
155
+ impact: z.ZodObject<{
156
+ conversations: z.ZodNumber;
157
+ items: z.ZodNumber;
158
+ }, z.core.$strip>;
159
+ settings: z.ZodObject<{
160
+ activity: z.ZodObject<{
161
+ retentionDays: z.ZodNumber;
162
+ maximumDays: z.ZodNumber;
163
+ defaultDays: z.ZodNumber;
164
+ }, z.core.$strip>;
165
+ conversations: z.ZodObject<{
166
+ sources: z.ZodObject<{
167
+ websiteVisitors: z.ZodBoolean;
168
+ signedInCustomers: z.ZodBoolean;
169
+ whatsapp: z.ZodBoolean;
170
+ }, z.core.$strip>;
171
+ state: z.ZodEnum<{
172
+ not_enabled: "not_enabled";
173
+ off: "off";
174
+ on: "on";
175
+ }>;
176
+ retentionDays: z.ZodOptional<z.ZodNumber>;
177
+ disabledByApplication: z.ZodOptional<z.ZodArray<z.ZodEnum<{
178
+ publicWebsite: "publicWebsite";
179
+ authenticatedWebsite: "authenticatedWebsite";
180
+ publicMessaging: "publicMessaging";
181
+ }>>>;
182
+ }, z.core.$strip>;
183
+ revision: z.ZodString;
184
+ canEdit: z.ZodBoolean;
185
+ }, z.core.$strip>;
186
+ dryRun: z.ZodBoolean;
187
+ shortensConversations: z.ZodBoolean;
188
+ }, z.core.$strip>;
189
+ }, z.core.$strip>;
190
+ //# sourceMappingURL=application-history-settings.d.ts.map