@noodleseed/one 0.172.1 → 0.173.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 (48) hide show
  1. package/dist/commands/solutions-draft-source.d.ts +9 -0
  2. package/dist/commands/solutions-draft-source.d.ts.map +1 -0
  3. package/dist/commands/solutions-draft-source.js +67 -0
  4. package/dist/commands/solutions-draft-source.js.map +1 -0
  5. package/dist/commands/solutions-drafts.d.ts +5 -0
  6. package/dist/commands/solutions-drafts.d.ts.map +1 -0
  7. package/dist/commands/solutions-drafts.js +159 -0
  8. package/dist/commands/solutions-drafts.js.map +1 -0
  9. package/dist/commands/solutions-ops.d.ts.map +1 -1
  10. package/dist/commands/solutions-ops.js +7 -1
  11. package/dist/commands/solutions-ops.js.map +1 -1
  12. package/dist/commands/solutions-page.d.ts +5 -0
  13. package/dist/commands/solutions-page.d.ts.map +1 -0
  14. package/dist/commands/solutions-page.js +85 -0
  15. package/dist/commands/solutions-page.js.map +1 -0
  16. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-solution-drafts.js +141 -0
  17. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-solution-page.js +57 -0
  18. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-solutions.js +4 -0
  19. package/node_modules/@noodle-borg/service/dist/application-drafts/contracts.js +11 -0
  20. package/node_modules/@noodle-borg/service/dist/application-drafts/paths.js +26 -0
  21. package/node_modules/@noodle-borg/service/dist/business-information/business-page-paths.js +14 -0
  22. package/node_modules/@noodle-borg/service/dist/business-information/business-page.d.ts +39 -0
  23. package/node_modules/@noodle-borg/service/dist/business-information/business-page.js +81 -0
  24. package/node_modules/@noodle-borg/service/dist/business-information/contracts.d.ts +2 -0
  25. package/node_modules/@noodle-borg/service/dist/business-information/in-memory-business-pages.js +37 -0
  26. package/node_modules/@noodle-borg/service/dist/business-information/in-memory-store.js +3 -0
  27. package/node_modules/@noodle-borg/service/dist/business-information/managed-solution-executable.js +11 -3
  28. package/node_modules/@noodle-borg/service/dist/routes/application-drafts.js +162 -0
  29. package/node_modules/@noodle-borg/service/dist/routes/business-information-channels.js +3 -0
  30. package/node_modules/@noodle-borg/service/dist/routes/business-information-dispatch.js +22 -0
  31. package/node_modules/@noodle-borg/service/dist/routes/business-information-pages.js +158 -0
  32. package/node_modules/@noodle-borg/service/dist/routes/service-probes.js +31 -0
  33. package/node_modules/@noodle-borg/service/dist/service.js +14 -18
  34. package/node_modules/@noodle-borg/service/dist/solution-installation-activation.js +3 -3
  35. package/node_modules/@noodle-borg/wire-contracts/dist/application-channels.d.ts +3 -0
  36. package/node_modules/@noodle-borg/wire-contracts/dist/application-channels.js +1 -0
  37. package/node_modules/@noodle-borg/wire-contracts/dist/application-drafts.d.ts +322 -0
  38. package/node_modules/@noodle-borg/wire-contracts/dist/application-drafts.js +152 -0
  39. package/node_modules/@noodle-borg/wire-contracts/dist/billing-org-transfer.d.ts +8 -8
  40. package/node_modules/@noodle-borg/wire-contracts/dist/billing-read.d.ts +5 -5
  41. package/node_modules/@noodle-borg/wire-contracts/dist/business-page.d.ts +157 -0
  42. package/node_modules/@noodle-borg/wire-contracts/dist/business-page.js +105 -0
  43. package/node_modules/@noodle-borg/wire-contracts/dist/business-workspaces.d.ts +22 -0
  44. package/node_modules/@noodle-borg/wire-contracts/dist/business-workspaces.js +15 -0
  45. package/node_modules/@noodle-borg/wire-contracts/dist/distribution.d.ts +10 -10
  46. package/node_modules/@noodle-borg/wire-contracts/dist/index.d.ts +3 -0
  47. package/node_modules/@noodle-borg/wire-contracts/dist/index.js +3 -0
  48. package/package.json +1 -1
@@ -64,6 +64,9 @@ export async function projectBusinessChannels(installation, canEdit, base, deps)
64
64
  revision: installation.revision,
65
65
  active: installation.intakeActive,
66
66
  canEdit,
67
+ ...(deps.pageOrigin
68
+ ? { businessPageUrl: `${deps.pageOrigin}/b/${installation.publicId}` }
69
+ : {}),
67
70
  ...(whatsapp
68
71
  ? {
69
72
  whatsapp: {
@@ -1,17 +1,21 @@
1
1
  import { OrganizationAgreementError } from '@noodle-borg/control-plane/portable';
2
2
  import { sendJson } from '@noodle-borg/transport-http';
3
+ import { parseApplicationDraftPath } from '../application-drafts/paths.js';
3
4
  import { BusinessNoticeError } from '../business-information/business-notice.js';
5
+ import { parseBusinessPagePath } from '../business-information/business-page-paths.js';
4
6
  import { InstallationCapacityError } from '../business-information/installation-capacity.js';
5
7
  import { NativeStorageLimitError } from '../business-information/native-storage-budget.js';
6
8
  import { SourceCredentialError } from '../business-information/source-credential-fence.js';
7
9
  import { SourceCapacityError } from '../business-information/source-custody-budget.js';
8
10
  import { respondRouteError } from '../http-util.js';
11
+ import { handleApplicationDraftRoute } from './application-drafts.js';
9
12
  import { handleBusinessGrants, handleManagedRecords, handleSolutionCatalog, handleSolutionInstallations, } from './business-information.js';
10
13
  import { handleApplicationActivity, } from './business-information-activity.js';
11
14
  import { handleBusinessChannels, } from './business-information-channels.js';
12
15
  import { handleApplicationConnectionCallback, handleApplicationConnections, } from './business-information-connections.js';
13
16
  import { handleBusinessNotice, handleOrganizationAgreement, } from './business-information-notice.js';
14
17
  import { handleSolutionInstallationOptions } from './business-information-onboarding.js';
18
+ import { handleBusinessPage, handlePublicBusinessPage } from './business-information-pages.js';
15
19
  import { parsePublicSolutionIntakePath, parseSolutionInstallationPath, parseSolutionInvitationAcceptPath, } from './business-information-paths.js';
16
20
  import { handlePublicSolutionIntake } from './business-information-public.js';
17
21
  import { handleBusinessInformationReaderFloor } from './business-information-reader-floor.js';
@@ -19,6 +23,24 @@ import { handleBusinessSettings } from './business-information-settings.js';
19
23
  import { handleCollectionSource } from './business-information-source.js';
20
24
  import { handleBusinessInvitationAccept, handleBusinessInvitations, handleEligibleBusinessAssignees, handleMySolutionInstallations, } from './business-information-staff.js';
21
25
  export function dispatchBusinessInformationRoutes(req, res, url, deps) {
26
+ const pageRef = parseBusinessPagePath(url.pathname);
27
+ const publicPage = /^\/v1\/business-pages\/(sol_[a-f0-9]{32})$/.exec(url.pathname);
28
+ if (pageRef || publicPage) {
29
+ if (!deps.pageOrigin || !deps.pageServiceUrl || !deps.registry || !deps.resolveEndpointBase)
30
+ return run(req, res, deps, () => Promise.resolve(sendJson(res, 404, { error: 'not found' })));
31
+ const pageDeps = {
32
+ ...deps,
33
+ registry: deps.registry,
34
+ resolveEndpointBase: deps.resolveEndpointBase,
35
+ };
36
+ return run(req, res, deps, () => pageRef
37
+ ? handleBusinessPage(req, res, pageRef, pageDeps)
38
+ : handlePublicBusinessPage(req, res, publicPage[1], pageDeps));
39
+ }
40
+ if (deps.authoring && parseApplicationDraftPath(url.pathname)) {
41
+ const draftDeps = { ...deps, ...deps.authoring, maxBody: deps.maxDraftBody ?? deps.maxBody };
42
+ return run(req, res, deps, () => handleApplicationDraftRoute(req, res, url, draftDeps));
43
+ }
22
44
  const agreement = /^\/v1\/orgs\/([a-z0-9][a-z0-9-]{0,62})\/agreement$/.exec(url.pathname);
23
45
  if (agreement?.[1])
24
46
  return run(req, res, deps, () => handleOrganizationAgreement(req, res, agreement[1], deps));
@@ -0,0 +1,158 @@
1
+ import { readJsonBody, sendJson } from '@noodle-borg/transport-http';
2
+ import { BusinessPagePublishRequestSchema, BusinessPageResponseSchema, BusinessPageSaveRequestSchema, PublicBusinessPageResponseSchema, } from '@noodle-borg/wire-contracts';
3
+ import { BusinessPageError, } from '../business-information/business-page.js';
4
+ import { businessPageMethods, } from '../business-information/business-page-paths.js';
5
+ import { requireIdentity, requireInstallationPermission } from './business-information.js';
6
+ import { projectBusinessChannels, } from './business-information-channels.js';
7
+ /** Publication custody remains valid independently of temporary assistant availability. */
8
+ async function pageContext(scope, deps) {
9
+ const installation = await deps.store.getInstallation(scope);
10
+ const generation = await deps.registry.getAppGeneration(scope.org, scope.app);
11
+ if (!installation ||
12
+ !generation ||
13
+ installation.applicationGeneration !== generation ||
14
+ (await deps.registry.getAppArchivedAt(scope.org, scope.app)) !== undefined ||
15
+ !deps.pageOrigin ||
16
+ !deps.pageServiceUrl ||
17
+ (deps.businessOnboarding && !(await deps.businessOnboarding.ready(installation))))
18
+ throw new BusinessPageError('business_page_not_ready');
19
+ const origin = new URL(deps.pageOrigin);
20
+ if (origin.origin !== deps.pageOrigin ||
21
+ !(origin.protocol === 'https:' ||
22
+ (origin.protocol === 'http:' && ['localhost', '127.0.0.1', '[::1]'].includes(origin.hostname))))
23
+ throw new BusinessPageError('business_page_not_ready');
24
+ return { installation, origin: origin.origin, serviceUrl: deps.pageServiceUrl };
25
+ }
26
+ /** Only a current, explicitly configured public assistant can be attached to a hosted page. */
27
+ async function pageReadiness(scope, deps) {
28
+ const { installation, origin, serviceUrl } = await pageContext(scope, deps);
29
+ if (!installation.intakeActive || deps.publicIntakeEnabled === false)
30
+ throw new BusinessPageError('business_page_not_ready');
31
+ const channels = await projectBusinessChannels(installation, false, serviceUrl, deps);
32
+ const assistant = channels.assistant;
33
+ if (assistant.status !== 'ready' ||
34
+ !assistant.origins.includes(origin) ||
35
+ !channels.deploymentId ||
36
+ !assistant.embedId ||
37
+ !assistant.serviceUrl ||
38
+ !assistant.scriptUrl)
39
+ throw new BusinessPageError('business_page_not_ready');
40
+ return {
41
+ deploymentId: channels.deploymentId,
42
+ assistant: {
43
+ embedId: assistant.embedId,
44
+ serviceUrl: assistant.serviceUrl,
45
+ scriptUrl: assistant.scriptUrl,
46
+ },
47
+ };
48
+ }
49
+ export async function handleBusinessPage(req, res, ref, deps) {
50
+ res.setHeader('cache-control', 'private, no-store');
51
+ if (!businessPageMethods(ref).includes(req.method ?? '')) {
52
+ res.setHeader('allow', businessPageMethods(ref).join(', '));
53
+ return sendJson(res, 405, { error: 'method not allowed' });
54
+ }
55
+ const identity = await requireIdentity(req, res, deps);
56
+ if (identity === false)
57
+ return;
58
+ const authorized = await requireInstallationPermission(res, ref, identity, 'installation:administer', deps);
59
+ if (!authorized)
60
+ return;
61
+ try {
62
+ let record = await deps.store.pages.get(authorized.scope);
63
+ if (req.method !== 'GET') {
64
+ const body = await readJsonBody(req, Math.min(deps.maxBody, 256 * 1024));
65
+ if (!body.ok)
66
+ return sendJson(res, body.status, { error: body.error });
67
+ let change;
68
+ if (ref.operation) {
69
+ const parsed = BusinessPagePublishRequestSchema.safeParse(body.value);
70
+ if (!parsed.success)
71
+ return invalidPage(res);
72
+ change = { operation: ref.operation, ...parsed.data };
73
+ }
74
+ else {
75
+ const parsed = BusinessPageSaveRequestSchema.safeParse(body.value);
76
+ if (!parsed.success)
77
+ return invalidPage(res);
78
+ change = { operation: 'save', ...parsed.data };
79
+ }
80
+ record = await deps.store.pages.update({ scope: authorized.scope, actorSubject: identity.subject, change }, () => pageReadiness(authorized.scope, deps));
81
+ }
82
+ return sendJson(res, 200, BusinessPageResponseSchema.parse({
83
+ ok: true,
84
+ data: {
85
+ revision: record?.revision ?? 0,
86
+ draft: record?.draft ?? null,
87
+ published: record?.published ?? null,
88
+ canEdit: true,
89
+ },
90
+ }));
91
+ }
92
+ catch (error) {
93
+ return pageFailure(res, error);
94
+ }
95
+ }
96
+ export async function handlePublicBusinessPage(req, res, publicId, deps) {
97
+ res.setHeader('cache-control', 'no-store');
98
+ res.setHeader('x-robots-tag', 'noindex');
99
+ if (req.method !== 'GET') {
100
+ res.setHeader('allow', 'GET');
101
+ return sendJson(res, 405, { error: 'method not allowed' });
102
+ }
103
+ try {
104
+ const installation = await deps.store.resolveInstallationByPublicId(publicId);
105
+ if (!installation)
106
+ return unavailablePage(res);
107
+ const record = await deps.store.pages.get(installation.scope);
108
+ if (!record?.published)
109
+ return unavailablePage(res);
110
+ await pageContext(installation.scope, deps);
111
+ const notice = await deps.store.getBusinessNotice(installation.scope);
112
+ if (notice?.revision !== record.published.noticeRevision)
113
+ return unavailablePage(res);
114
+ const ready = await pageReadiness(installation.scope, deps).catch((error) => {
115
+ if (error instanceof BusinessPageError)
116
+ return undefined;
117
+ throw error;
118
+ });
119
+ return sendJson(res, 200, PublicBusinessPageResponseSchema.parse({
120
+ ok: true,
121
+ data: {
122
+ publicId,
123
+ content: record.published.content,
124
+ notice: record.published.notice,
125
+ assistant: ready?.deploymentId === record.published.deploymentId ? ready.assistant : null,
126
+ },
127
+ }));
128
+ }
129
+ catch (error) {
130
+ if (error instanceof BusinessPageError)
131
+ return unavailablePage(res);
132
+ return pageFailure(res, error);
133
+ }
134
+ }
135
+ function unavailablePage(res) {
136
+ sendJson(res, 404, { code: 'page_unavailable', error: 'This page is not available.' });
137
+ }
138
+ function invalidPage(res) {
139
+ sendJson(res, 400, {
140
+ code: 'business_page_invalid',
141
+ error: 'Check the page content and revision.',
142
+ });
143
+ }
144
+ function pageFailure(res, error) {
145
+ if (error instanceof BusinessPageError) {
146
+ sendJson(res, error.code === 'business_page_forbidden' ? 403 : 409, {
147
+ code: error.code,
148
+ error: error.message,
149
+ });
150
+ return;
151
+ }
152
+ // Neither decrypted content nor provider/parser exceptions may escape via generic route logging.
153
+ sendJson(res, 503, {
154
+ code: 'page_unavailable',
155
+ error: 'The page service is temporarily unavailable.',
156
+ });
157
+ }
158
+ //# sourceMappingURL=business-information-pages.js.map
@@ -0,0 +1,31 @@
1
+ import { applySecurityHeaders, sendJson } from '@noodle-borg/transport-http';
2
+ import { serviceInfoPayload } from '../build-info.js';
3
+ export function createServiceProbeDispatcher(deps) {
4
+ return (req, res, url) => {
5
+ if (req.method !== 'GET' || !['/healthz', '/readyz', '/v1/service/info'].includes(url.pathname))
6
+ return false;
7
+ handleServiceProbe(req, res, url, deps);
8
+ return true;
9
+ };
10
+ }
11
+ function handleServiceProbe(req, res, url, { tls, moduleHost, buildInfo, options, whatsapp }) {
12
+ // Liveness/readiness probes: un-gated and **not** HTTPS-enforced — Cloud Run's internal probe is plain
13
+ // HTTP, so enforcing HTTPS here would `426` the probe and the revision would never go healthy (ADR 0034).
14
+ // `/healthz` is a pure liveness 200 (no store touch); `/readyz` reflects the injected readiness probe.
15
+ if (req.method === 'GET' && (url.pathname === '/healthz' || url.pathname === '/readyz')) {
16
+ applySecurityHeaders(res, tls);
17
+ if (url.pathname === '/healthz')
18
+ return sendJson(res, 200, { status: 'ok' });
19
+ void Promise.resolve(moduleHost.ready())
20
+ .then((ready) => sendJson(res, ready ? 200 : 503, { status: ready ? 'ready' : 'unready' }))
21
+ .catch(() => sendJson(res, 503, { status: 'unready' }));
22
+ return;
23
+ }
24
+ // Deployed-version visibility (ADR 0080): un-gated, non-HTTPS-enforced like the probes so the
25
+ // post-deploy smoke can confirm exactly which commit is live. Non-sensitive fields only.
26
+ if (req.method === 'GET' && url.pathname === '/v1/service/info') {
27
+ applySecurityHeaders(res, tls);
28
+ return sendJson(res, 200, serviceInfoPayload(buildInfo, options.developerMcp === true, whatsapp !== undefined));
29
+ }
30
+ }
31
+ //# sourceMappingURL=service-probes.js.map
@@ -12,7 +12,7 @@ import { createArchivePreflight } from './archive-preflight.js';
12
12
  import { ArchiveSweeper, resolveArchiveRetentionDays } from './archive-sweeper.js';
13
13
  import { serveLocalAsset } from './assets.js';
14
14
  import { assistantRouteDependencies } from './assistant-composition.js';
15
- import { resolveBuildInfo, serviceInfoPayload } from './build-info.js';
15
+ import { resolveBuildInfo } from './build-info.js';
16
16
  import { createBusinessInformationRuntime, resolvePrivateInstallationDefinition, } from './business-information-runtime.js';
17
17
  import { serviceCapabilityReport } from './capabilities.js';
18
18
  import { createWhatsAppRuntime } from './channels/composition.js';
@@ -52,6 +52,7 @@ import { dispatchProtectedResourceMetadata } from './routes/protected-resource-m
52
52
  import { dispatchResourceReads } from './routes/resource-read-dispatch.js';
53
53
  import { handleRollback } from './routes/rollback.js';
54
54
  import { createServicePrincipalDispatcher } from './routes/service-principals-dispatch.js';
55
+ import { createServiceProbeDispatcher } from './routes/service-probes.js';
55
56
  import { dispatchWhatsAppRoutes } from './routes/whatsapp.js';
56
57
  import { servicePrincipalDataPlaneHooks } from './service-principal-data-plane.js';
57
58
  import { InMemoryAlertRuleStore } from './store/alert-rules.js';
@@ -201,20 +202,17 @@ export function createServiceHandler(registry, options = {}) {
201
202
  installations: businessInformationStore,
202
203
  activity,
203
204
  });
205
+ const dispatchProbe = createServiceProbeDispatcher({
206
+ tls,
207
+ moduleHost,
208
+ buildInfo,
209
+ options,
210
+ whatsapp,
211
+ });
204
212
  return (req, res) => {
205
213
  const url = new URL(req.url ?? '/', 'http://localhost');
206
- // Liveness/readiness probes: un-gated and **not** HTTPS-enforced — Cloud Run's internal probe is plain
207
- // HTTP, so enforcing HTTPS here would `426` the probe and the revision would never go healthy (ADR 0034).
208
- // `/healthz` is a pure liveness 200 (no store touch); `/readyz` reflects the injected readiness probe.
209
- if (req.method === 'GET' && (url.pathname === '/healthz' || url.pathname === '/readyz')) {
210
- applySecurityHeaders(res, tls);
211
- if (url.pathname === '/healthz')
212
- return sendJson(res, 200, { status: 'ok' });
213
- void Promise.resolve(moduleHost.ready())
214
- .then((ready) => sendJson(res, ready ? 200 : 503, { status: ready ? 'ready' : 'unready' }))
215
- .catch(() => sendJson(res, 503, { status: 'unready' }));
214
+ if (dispatchProbe(req, res, url))
216
215
  return;
217
- }
218
216
  if (options.developerMcp === true && url.pathname === DEVELOPER_MCP_PATH) {
219
217
  const mount = createDeveloperMcpMountOptions({
220
218
  registry,
@@ -228,12 +226,6 @@ export function createServiceHandler(registry, options = {}) {
228
226
  void handleDeveloperMcpRequest(req, res, mount).catch((error) => respondRouteError(logger, res, 'developer.mcp.failed', error));
229
227
  return;
230
228
  }
231
- // Deployed-version visibility (ADR 0080): un-gated, non-HTTPS-enforced like the probes so the
232
- // post-deploy smoke can confirm exactly which commit is live. Non-sensitive fields only.
233
- if (req.method === 'GET' && url.pathname === '/v1/service/info') {
234
- applySecurityHeaders(res, tls);
235
- return sendJson(res, 200, serviceInfoPayload(buildInfo, options.developerMcp === true, whatsapp !== undefined));
236
- }
237
229
  if (url.pathname.startsWith('/v1/') && rejectIncompatibleCli(req, res, buildInfo, tls))
238
230
  return;
239
231
  if (req.method === 'GET' || req.method === 'HEAD') {
@@ -305,6 +297,10 @@ export function createServiceHandler(registry, options = {}) {
305
297
  if (businessInformationStore !== undefined &&
306
298
  options.businessInformationEnabled !== false &&
307
299
  dispatchBusinessInformationRoutes(req, res, url, {
300
+ authoring: options.businessAuthoring,
301
+ pageOrigin: options.businessPageOrigin,
302
+ pageServiceUrl: options.publicBaseUrl,
303
+ maxDraftBody: maxDeployBody,
308
304
  ...(whatsapp ? { readWhatsApp: whatsapp.projection.bind(whatsapp) } : {}),
309
305
  store: businessInformationStore,
310
306
  ...(businessOnboarding ? { businessOnboarding } : {}),
@@ -95,7 +95,7 @@ export async function activateSolutionInstallation(input, dependencies) {
95
95
  }
96
96
  return { ok: true, deploymentId };
97
97
  };
98
- const source = await executableSource(installation, dependencies.registry);
98
+ const source = await executableSource(installation, dependencies.registry, dependencies.options.businessPageOrigin);
99
99
  if (!source.ok)
100
100
  return source;
101
101
  const current = await dependencies.registry.getActiveByTenant(tenant);
@@ -152,13 +152,13 @@ export async function activateSolutionInstallation(input, dependencies) {
152
152
  };
153
153
  return bind(deployed.result.deploymentId, false);
154
154
  }
155
- async function executableSource(installation, registry) {
155
+ async function executableSource(installation, registry, hostedPageOrigin) {
156
156
  const reference = installation.definition.reference;
157
157
  if (reference.kind === 'managed') {
158
158
  return {
159
159
  ok: true,
160
160
  value: {
161
- manifest: JSON.stringify(managedSolutionManifest(installation.definition)),
161
+ manifest: JSON.stringify(managedSolutionManifest(installation.definition, hostedPageOrigin)),
162
162
  accessMode: 'public',
163
163
  serverVersion: '1',
164
164
  },
@@ -3,6 +3,7 @@ export declare const ApplicationChannelsProjectionSchema: z.ZodObject<{
3
3
  revision: z.ZodNumber;
4
4
  active: z.ZodBoolean;
5
5
  canEdit: z.ZodBoolean;
6
+ businessPageUrl: z.ZodOptional<z.ZodURL>;
6
7
  deploymentId: z.ZodOptional<z.ZodString>;
7
8
  mcp: z.ZodObject<{
8
9
  status: z.ZodEnum<{
@@ -56,6 +57,7 @@ export declare const ApplicationChannelsResponseSchema: z.ZodObject<{
56
57
  revision: z.ZodNumber;
57
58
  active: z.ZodBoolean;
58
59
  canEdit: z.ZodBoolean;
60
+ businessPageUrl: z.ZodOptional<z.ZodURL>;
59
61
  deploymentId: z.ZodOptional<z.ZodString>;
60
62
  mcp: z.ZodObject<{
61
63
  status: z.ZodEnum<{
@@ -109,6 +111,7 @@ export declare const ApplicationChannelsClientResponseSchema: z.ZodObject<{
109
111
  revision: z.ZodNumber;
110
112
  active: z.ZodBoolean;
111
113
  canEdit: z.ZodBoolean;
114
+ businessPageUrl: z.ZodOptional<z.ZodURL>;
112
115
  deploymentId: z.ZodOptional<z.ZodString>;
113
116
  mcp: z.ZodObject<{
114
117
  status: z.ZodEnum<{
@@ -51,6 +51,7 @@ export const ApplicationChannelsProjectionSchema = z
51
51
  revision: z.number().int().positive(),
52
52
  active: z.boolean(),
53
53
  canEdit: z.boolean(),
54
+ businessPageUrl: httpUrl.optional(),
54
55
  deploymentId: z.string().min(1).max(256).optional(),
55
56
  mcp,
56
57
  assistant,