@noodleseed/one 0.174.0 → 0.175.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/solutions-activity.js +1 -1
- package/dist/commands/solutions-activity.js.map +1 -1
- package/dist/commands/solutions-drafts.d.ts.map +1 -1
- package/dist/commands/solutions-drafts.js +36 -9
- package/dist/commands/solutions-drafts.js.map +1 -1
- package/dist/commands/solutions-native-lifecycle.d.ts +5 -0
- package/dist/commands/solutions-native-lifecycle.d.ts.map +1 -0
- package/dist/commands/solutions-native-lifecycle.js +77 -0
- package/dist/commands/solutions-native-lifecycle.js.map +1 -0
- package/dist/commands/solutions-ops.d.ts.map +1 -1
- package/dist/commands/solutions-ops.js +3 -0
- package/dist/commands/solutions-ops.js.map +1 -1
- package/dist/commands/solutions-workspace.d.ts.map +1 -1
- package/dist/commands/solutions-workspace.js +36 -11
- package/dist/commands/solutions-workspace.js.map +1 -1
- package/dist/commands/whatsapp-output.d.ts.map +1 -1
- package/dist/commands/whatsapp-output.js +20 -4
- package/dist/commands/whatsapp-output.js.map +1 -1
- package/node_modules/@noodle-borg/admission-limits/dist/public-record-admission.d.ts +16 -9
- package/node_modules/@noodle-borg/admission-limits/dist/public-record-admission.js +5 -2
- package/node_modules/@noodle-borg/agent-kit/dist/curated/error-fixes.js +9 -0
- package/node_modules/@noodle-borg/agent-kit/dist/generated/example-files.js +5 -5
- package/node_modules/@noodle-borg/agent-kit/dist/generated/surface.js +9 -0
- package/node_modules/@noodle-borg/agent-kit/dist/skill-authoring-refs.js +1 -1
- package/node_modules/@noodle-borg/agent-kit/dist/skill-embedded-assistant-ref.js +13 -1
- package/node_modules/@noodle-borg/agent-kit/package.json +1 -1
- package/node_modules/@noodle-borg/assistant-gateway/dist/channel-coordinator.d.ts +5 -3
- package/node_modules/@noodle-borg/assistant-gateway/dist/channel-coordinator.js +5 -4
- package/node_modules/@noodle-borg/assistant-gateway/dist/channel-inbox.js +6 -2
- package/node_modules/@noodle-borg/assistant-gateway/dist/channel-store.d.ts +1 -1
- package/node_modules/@noodle-borg/assistant-gateway/dist/channel-types.d.ts +12 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/channel-work.d.ts +7 -2
- package/node_modules/@noodle-borg/assistant-gateway/dist/channel-work.js +14 -4
- package/node_modules/@noodle-borg/assistant-gateway/dist/collection-capture.js +104 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/collection-judgment.js +93 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/collection-ledger.d.ts +105 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/collection-ledger.js +183 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/collection-model-call.js +38 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/collection-parsers.d.ts +22 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/collection-parsers.js +109 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/collection-review.d.ts +21 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/collection-review.js +44 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/collection-spec.d.ts +18 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/collection-spec.js +86 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/collection-store.d.ts +11 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/collection-store.js +18 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/messaging-tool-dispatch.d.ts +20 -1
- package/node_modules/@noodle-borg/assistant-gateway/dist/messaging-tool-dispatch.js +38 -2
- package/node_modules/@noodle-borg/assistant-gateway/dist/model-runtime.js +3 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/portable.d.ts +5 -0
- package/node_modules/@noodle-borg/assistant-gateway/dist/portable.js +5 -0
- package/node_modules/@noodle-borg/assistant-gateway/package.json +1 -1
- package/node_modules/@noodle-borg/authoring/dist/index.d.ts +1 -0
- package/node_modules/@noodle-borg/authoring/dist/interaction.d.ts +49 -0
- package/node_modules/@noodle-borg/authoring/dist/interaction.js +25 -0
- package/node_modules/@noodle-borg/authoring/dist/server.d.ts +3 -0
- package/node_modules/@noodle-borg/authoring/dist/server.js +4 -0
- package/node_modules/@noodle-borg/authoring/package.json +6 -1
- package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-channels.js +1 -1
- package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-solution-drafts.js +7 -0
- package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-solution-native-lifecycle.js +43 -0
- package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-solution-records.js +154 -0
- package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-solution-workspace.js +8 -1
- package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-solutions.js +2 -149
- package/node_modules/@noodle-borg/compiler/dist/artifact/assemble.js +2 -1
- package/node_modules/@noodle-borg/compiler/dist/artifact/types.d.ts +33 -0
- package/node_modules/@noodle-borg/compiler/dist/artifact/version.d.ts +2 -1
- package/node_modules/@noodle-borg/compiler/dist/artifact/version.js +2 -1
- package/node_modules/@noodle-borg/compiler/dist/compile.js +5 -0
- package/node_modules/@noodle-borg/compiler/dist/errors.d.ts +1 -1
- package/node_modules/@noodle-borg/compiler/dist/index.d.ts +2 -2
- package/node_modules/@noodle-borg/compiler/dist/index.js +1 -1
- package/node_modules/@noodle-borg/compiler/dist/manifest/interaction-schema.d.ts +41 -0
- package/node_modules/@noodle-borg/compiler/dist/manifest/interaction-schema.js +62 -0
- package/node_modules/@noodle-borg/compiler/dist/manifest/interaction-validation.js +220 -0
- package/node_modules/@noodle-borg/compiler/dist/manifest/schema.d.ts +60 -4
- package/node_modules/@noodle-borg/compiler/dist/manifest/schema.js +7 -1
- package/node_modules/@noodle-borg/compiler/dist/manifest/website-projection.d.ts +9 -1
- package/node_modules/@noodle-borg/compiler/dist/manifest/website-projection.js +58 -10
- package/node_modules/@noodle-borg/control-plane/dist/in-memory-atomic-state.d.ts +8 -0
- package/node_modules/@noodle-borg/control-plane/dist/in-memory-atomic-state.js +136 -0
- package/node_modules/@noodle-borg/control-plane/dist/in-memory-control-plane-store.d.ts +7 -0
- package/node_modules/@noodle-borg/control-plane/dist/in-memory-control-plane-store.js +16 -24
- package/node_modules/@noodle-borg/control-plane/dist/in-memory-organization-store.d.ts +4 -2
- package/node_modules/@noodle-borg/control-plane/dist/in-memory-organization-store.js +8 -6
- package/node_modules/@noodle-borg/control-plane/dist/mcp-subdomain-claims.d.ts +2 -1
- package/node_modules/@noodle-borg/control-plane/dist/mcp-subdomain-claims.js +13 -8
- package/node_modules/@noodle-borg/control-plane/dist/organization-agreements.d.ts +13 -4
- package/node_modules/@noodle-borg/control-plane/dist/organization-agreements.js +23 -7
- package/node_modules/@noodle-borg/control-plane/dist/portable.d.ts +2 -1
- package/node_modules/@noodle-borg/control-plane/dist/portable.js +1 -0
- package/node_modules/@noodle-borg/module/dist/platform-human-identity.d.ts +5 -2
- package/node_modules/@noodle-borg/runtime/dist/connector/types.d.ts +16 -4
- package/node_modules/@noodle-borg/runtime/dist/execute.d.ts +3 -6
- package/node_modules/@noodle-borg/runtime/dist/index.d.ts +1 -1
- package/node_modules/@noodle-borg/service/dist/application-activity.js +85 -63
- package/node_modules/@noodle-borg/service/dist/application-drafts/contracts.js +9 -0
- package/node_modules/@noodle-borg/service/dist/application-drafts/paths.js +2 -2
- package/node_modules/@noodle-borg/service/dist/application-runtime-target.js +1 -1
- package/node_modules/@noodle-borg/service/dist/business-information/contracts.d.ts +18 -4
- package/node_modules/@noodle-borg/service/dist/business-information/in-memory-business-pages.js +3 -5
- package/node_modules/@noodle-borg/service/dist/business-information/in-memory-installation-lifecycle.js +8 -6
- package/node_modules/@noodle-borg/service/dist/business-information/in-memory-native-lifecycle.js +80 -0
- package/node_modules/@noodle-borg/service/dist/business-information/in-memory-store.js +27 -31
- package/node_modules/@noodle-borg/service/dist/business-information/memory-native-retention.js +29 -0
- package/node_modules/@noodle-borg/service/dist/business-information/model.js +9 -2
- package/node_modules/@noodle-borg/service/dist/business-information/native-query.js +3 -1
- package/node_modules/@noodle-borg/service/dist/business-information/native-record-lifecycle.d.ts +27 -0
- package/node_modules/@noodle-borg/service/dist/business-information/native-record-lifecycle.js +63 -0
- package/node_modules/@noodle-borg/service/dist/business-information/principal-authority.d.ts +3 -1
- package/node_modules/@noodle-borg/service/dist/business-information/principal-authority.js +9 -4
- package/node_modules/@noodle-borg/service/dist/business-information/staff-authority.d.ts +16 -0
- package/node_modules/@noodle-borg/service/dist/business-information/staff-authority.js +60 -0
- package/node_modules/@noodle-borg/service/dist/business-information/workspace-permissions.js +18 -0
- package/node_modules/@noodle-borg/service/dist/business-information-runtime.js +1 -0
- package/node_modules/@noodle-borg/service/dist/business-onboarding.js +16 -3
- package/node_modules/@noodle-borg/service/dist/business-workspaces/contracts.d.ts +110 -0
- package/node_modules/@noodle-borg/service/dist/business-workspaces/permissions.d.ts +7 -0
- package/node_modules/@noodle-borg/service/dist/business-workspaces/store.d.ts +102 -0
- package/node_modules/@noodle-borg/service/dist/channels/360dialog.js +70 -8
- package/node_modules/@noodle-borg/service/dist/channels/capability-report.js +73 -0
- package/node_modules/@noodle-borg/service/dist/channels/collection-turn.js +232 -0
- package/node_modules/@noodle-borg/service/dist/channels/composition.js +1 -0
- package/node_modules/@noodle-borg/service/dist/channels/messaging-eligibility.js +45 -0
- package/node_modules/@noodle-borg/service/dist/channels/reply-buttons.js +23 -0
- package/node_modules/@noodle-borg/service/dist/channels/runtime.js +127 -33
- package/node_modules/@noodle-borg/service/dist/native-record-connector.js +19 -4
- package/node_modules/@noodle-borg/service/dist/routes/application-drafts.js +44 -2
- package/node_modules/@noodle-borg/service/dist/routes/assistant-agent.js +4 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-authoring-dispatch.js +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/business-information-access.js +39 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-information-activity.js +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/business-information-channels.js +2 -2
- package/node_modules/@noodle-borg/service/dist/routes/business-information-connections.js +10 -4
- package/node_modules/@noodle-borg/service/dist/routes/business-information-dispatch.js +11 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-information-installation.js +3 -1
- package/node_modules/@noodle-borg/service/dist/routes/business-information-notice.js +6 -2
- package/node_modules/@noodle-borg/service/dist/routes/business-information-pages.js +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/business-information-paths.js +1 -1
- package/node_modules/@noodle-borg/service/dist/routes/business-information-record-create.js +7 -2
- package/node_modules/@noodle-borg/service/dist/routes/business-information-record-reads.js +2 -2
- package/node_modules/@noodle-borg/service/dist/routes/business-information-records.js +332 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-information-settings.js +6 -3
- package/node_modules/@noodle-borg/service/dist/routes/business-information-staff.js +9 -5
- package/node_modules/@noodle-borg/service/dist/routes/business-information.js +12 -356
- package/node_modules/@noodle-borg/service/dist/routes/business-native-lifecycle.js +46 -0
- package/node_modules/@noodle-borg/service/dist/routes/business-workspaces.js +14 -1
- package/node_modules/@noodle-borg/service/dist/service.js +1 -0
- package/node_modules/@noodle-borg/service/dist/web-capabilities.js +3 -1
- package/node_modules/@noodle-borg/service/package.json +2 -1
- package/node_modules/@noodle-borg/wire-contracts/dist/application-draft-validation.d.ts +59 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/application-draft-validation.js +38 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/business-information.d.ts +144 -50
- package/node_modules/@noodle-borg/wire-contracts/dist/business-information.js +44 -4
- package/node_modules/@noodle-borg/wire-contracts/dist/business-workspaces.d.ts +70 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/business-workspaces.js +31 -1
- package/node_modules/@noodle-borg/wire-contracts/dist/index.d.ts +2 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/index.js +2 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/native-record-lifecycle.d.ts +81 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/native-record-lifecycle.js +39 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/whatsapp.d.ts +26 -0
- package/node_modules/@noodle-borg/wire-contracts/dist/whatsapp.js +24 -1
- package/node_modules/@noodleseed/assistant/package.json +1 -1
- package/package.json +2 -2
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import { readJsonBody, sendJson } from '@noodle-borg/transport-http';
|
|
2
|
-
import { BusinessGrantCreateRequestSchema, formatWireError,
|
|
3
|
-
import {
|
|
2
|
+
import { BusinessGrantCreateRequestSchema, formatWireError, SolutionInstallationCreateRequestSchema, SolutionInstallationIntakeRequestSchema, } from '@noodle-borg/wire-contracts';
|
|
3
|
+
import { admitBusinessTarget } from '../business-api-admission.js';
|
|
4
4
|
import { resolveInstallDefinition } from '../business-information/definition-resolver.js';
|
|
5
|
-
import { BUILT_IN_SOLUTION_PROFILES,
|
|
5
|
+
import { BUILT_IN_SOLUTION_PROFILES, MANAGED_SOLUTION_PROFILE_KEYS, validateCollectionEnabled, } from '../business-information/portable.js';
|
|
6
6
|
import { sendForbidden } from '../http-util.js';
|
|
7
|
-
import {
|
|
7
|
+
import { requireIdentity, requireInstallationGrant, requireInstallationPermission, resolveBusinessStaffGrant, runBusinessStaffOperation, } from './business-information-access.js';
|
|
8
8
|
import { installationProjection, retryInstallationActivation, stableInstallationId, } from './business-information-installation.js';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { expectedRevision, mutationPermission, parseNativeRecordQuery, parseBusinessPaging as parsePaging, requestIdempotencyKey, } from './business-information-request.js';
|
|
12
|
-
import { collectionToWire, externalRecordToWire, grantToWire, profileToWire, recordDetailToWire, recordToWire, } from './business-information-wire.js';
|
|
9
|
+
import { expectedRevision } from './business-information-request.js';
|
|
10
|
+
import { grantToWire, profileToWire } from './business-information-wire.js';
|
|
13
11
|
import { canManageMembers } from './org-admin.js';
|
|
14
12
|
export function handleSolutionCatalog(req, res) {
|
|
15
13
|
if (req.method !== 'GET') {
|
|
@@ -70,7 +68,7 @@ export async function handleSolutionInstallations(req, res, ref, deps) {
|
|
|
70
68
|
code: 'installation_conflict',
|
|
71
69
|
});
|
|
72
70
|
}
|
|
73
|
-
const grant = await deps
|
|
71
|
+
const grant = await resolveBusinessStaffGrant(deps, result.installation.scope, identity.subject);
|
|
74
72
|
if (grant === undefined || grant.revokedAt !== undefined) {
|
|
75
73
|
return sendForbidden(res, 'business grant required');
|
|
76
74
|
}
|
|
@@ -107,7 +105,7 @@ export async function handleSolutionInstallations(req, res, ref, deps) {
|
|
|
107
105
|
const installations = await deps.store.listInstallations(ref.org);
|
|
108
106
|
const permitted = [];
|
|
109
107
|
for (const installation of installations) {
|
|
110
|
-
const grant = await deps
|
|
108
|
+
const grant = await resolveBusinessStaffGrant(deps, installation.scope, identity.subject);
|
|
111
109
|
if (grant !== undefined && grant.revokedAt === undefined) {
|
|
112
110
|
permitted.push({ installation, role: grant.role });
|
|
113
111
|
}
|
|
@@ -142,12 +140,12 @@ export async function handleSolutionInstallations(req, res, ref, deps) {
|
|
|
142
140
|
const parsed = SolutionInstallationIntakeRequestSchema.safeParse(body.value);
|
|
143
141
|
if (!parsed.success)
|
|
144
142
|
return invalid(res, parsed.error);
|
|
145
|
-
const result = await deps.store.setIntakeState({
|
|
143
|
+
const result = await runBusinessStaffOperation(deps, authorized.scope, identity.subject, 'installation:administer', () => deps.store.setIntakeState({
|
|
146
144
|
scope: authorized.scope,
|
|
147
145
|
expectedRevision: parsed.data.expectedRevision,
|
|
148
146
|
active: parsed.data.active,
|
|
149
147
|
actorSubject: identity.subject,
|
|
150
|
-
});
|
|
148
|
+
}));
|
|
151
149
|
if (!result.ok)
|
|
152
150
|
return mutationFailure(res, result);
|
|
153
151
|
return sendJson(res, 200, {
|
|
@@ -213,350 +211,8 @@ export async function handleBusinessGrants(req, res, ref, deps) {
|
|
|
213
211
|
}
|
|
214
212
|
return methodNotAllowed(res);
|
|
215
213
|
}
|
|
216
|
-
export
|
|
217
|
-
|
|
218
|
-
if (identity === false)
|
|
219
|
-
return;
|
|
220
|
-
if (ref.collection === undefined)
|
|
221
|
-
return sendJson(res, 404, { error: 'not found' });
|
|
222
|
-
const collection = ref.collection;
|
|
223
|
-
if (ref.action === 'activity' && req.method === 'GET' && ref.recordId !== undefined) {
|
|
224
|
-
const authorized = await requireInstallationPermission(res, ref, identity, 'records:read', deps);
|
|
225
|
-
if (authorized === undefined)
|
|
226
|
-
return;
|
|
227
|
-
const definition = enabledCollection(res, authorized.installation, collection);
|
|
228
|
-
if (definition === undefined)
|
|
229
|
-
return;
|
|
230
|
-
if (definition.authority.authority === 'external') {
|
|
231
|
-
return sendJson(res, 200, { ok: true, data: { activities: [] } });
|
|
232
|
-
}
|
|
233
|
-
return sendNativeRecordActivity(res, url, authorized.installation.scope, collection, ref.recordId, deps.store);
|
|
234
|
-
}
|
|
235
|
-
if (ref.action === 'export' && req.method === 'GET') {
|
|
236
|
-
const authorized = await requireInstallationPermission(res, ref, identity, 'records:export', deps);
|
|
237
|
-
if (authorized === undefined)
|
|
238
|
-
return;
|
|
239
|
-
const definition = enabledCollection(res, authorized.installation, collection);
|
|
240
|
-
if (definition === undefined)
|
|
241
|
-
return;
|
|
242
|
-
const paging = parsePaging(url, 500);
|
|
243
|
-
if (!paging.ok)
|
|
244
|
-
return sendJson(res, 400, { error: paging.error });
|
|
245
|
-
if (definition.authority.authority === 'external') {
|
|
246
|
-
return sendExternalRecordPage(res, authorized.installation, definition, { ...paging.value, limit: paging.value.limit ?? 500 }, deps);
|
|
247
|
-
}
|
|
248
|
-
const page = await cursorRequest(res, () => deps.store.exportRequests({
|
|
249
|
-
scope: authorized.installation.scope,
|
|
250
|
-
collectionKey: collection,
|
|
251
|
-
...paging.value,
|
|
252
|
-
includeDeleted: url.searchParams.get('includeDeleted') === 'true',
|
|
253
|
-
}));
|
|
254
|
-
if (page === undefined)
|
|
255
|
-
return;
|
|
256
|
-
return sendJson(res, 200, {
|
|
257
|
-
ok: true,
|
|
258
|
-
data: {
|
|
259
|
-
records: page.records.map((record) => ({
|
|
260
|
-
...recordToWire(record),
|
|
261
|
-
...(record.content ? { notes: record.content.notes } : {}),
|
|
262
|
-
})),
|
|
263
|
-
...(page.nextCursor === undefined ? {} : { nextCursor: page.nextCursor }),
|
|
264
|
-
},
|
|
265
|
-
});
|
|
266
|
-
}
|
|
267
|
-
if (ref.recordId === undefined && req.method === 'GET') {
|
|
268
|
-
const authorized = await requireInstallationPermission(res, ref, identity, 'records:read', deps);
|
|
269
|
-
if (authorized === undefined)
|
|
270
|
-
return;
|
|
271
|
-
const definition = enabledCollection(res, authorized.installation, collection);
|
|
272
|
-
if (definition === undefined)
|
|
273
|
-
return;
|
|
274
|
-
const paging = parsePaging(url, 100);
|
|
275
|
-
if (!paging.ok)
|
|
276
|
-
return sendJson(res, 400, { error: paging.error });
|
|
277
|
-
const query = parseNativeRecordQuery(url);
|
|
278
|
-
if (!query.ok)
|
|
279
|
-
return sendJson(res, 400, { error: query.error, code: 'invalid_query' });
|
|
280
|
-
if (definition.authority.authority === 'external') {
|
|
281
|
-
if (Object.keys(query.value).length > 0)
|
|
282
|
-
return sendJson(res, 400, {
|
|
283
|
-
error: 'Field and date queries currently require a native collection.',
|
|
284
|
-
code: 'invalid_query',
|
|
285
|
-
});
|
|
286
|
-
return sendExternalRecordPage(res, authorized.installation, definition, paging.value, deps);
|
|
287
|
-
}
|
|
288
|
-
const statusValue = url.searchParams.get('status');
|
|
289
|
-
const status = statusValue === null ? undefined : ManagedRecordStatusSchema.safeParse(statusValue);
|
|
290
|
-
if (status !== undefined && !status.success)
|
|
291
|
-
return sendJson(res, 400, { error: 'invalid status' });
|
|
292
|
-
const assigneeSubject = url.searchParams.get('assigneeSubject') ?? undefined;
|
|
293
|
-
const page = await cursorRequest(res, () => deps.store.listRequests({
|
|
294
|
-
scope: authorized.installation.scope,
|
|
295
|
-
collectionKey: collection,
|
|
296
|
-
...paging.value,
|
|
297
|
-
...query.value,
|
|
298
|
-
...(status === undefined ? {} : { status: status.data }),
|
|
299
|
-
...(assigneeSubject === undefined ? {} : { assigneeSubject }),
|
|
300
|
-
includeDeleted: url.searchParams.get('includeDeleted') === 'true',
|
|
301
|
-
}));
|
|
302
|
-
if (page === undefined)
|
|
303
|
-
return;
|
|
304
|
-
return sendJson(res, 200, {
|
|
305
|
-
ok: true,
|
|
306
|
-
data: {
|
|
307
|
-
records: page.records.map(recordToWire),
|
|
308
|
-
...(page.nextCursor === undefined ? {} : { nextCursor: page.nextCursor }),
|
|
309
|
-
},
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
if (ref.recordId === undefined && req.method === 'POST') {
|
|
313
|
-
const authorized = await requireInstallationPermission(res, ref, identity, 'records:create', deps);
|
|
314
|
-
if (authorized === undefined)
|
|
315
|
-
return;
|
|
316
|
-
const definition = enabledCollection(res, authorized.installation, collection);
|
|
317
|
-
if (definition === undefined)
|
|
318
|
-
return;
|
|
319
|
-
if (definition.authority.authority === 'external') {
|
|
320
|
-
return unsupportedExternalOperation(res, 'create');
|
|
321
|
-
}
|
|
322
|
-
const idempotencyKey = requestIdempotencyKey(req);
|
|
323
|
-
if (idempotencyKey === undefined) {
|
|
324
|
-
return sendJson(res, 400, { error: 'Idempotency-Key header is required (1-128 characters)' });
|
|
325
|
-
}
|
|
326
|
-
const body = await readJsonBody(req, deps.maxBody);
|
|
327
|
-
if (!body.ok)
|
|
328
|
-
return sendJson(res, body.status, { error: body.error });
|
|
329
|
-
const parsed = ManagedRecordCreateRequestSchema.safeParse(body.value);
|
|
330
|
-
if (!parsed.success)
|
|
331
|
-
return invalid(res, parsed.error);
|
|
332
|
-
const result = await createNativeRecord(res, deps, {
|
|
333
|
-
installation: authorized.installation,
|
|
334
|
-
collection,
|
|
335
|
-
idempotencyKey,
|
|
336
|
-
payload: parsed.data.payload,
|
|
337
|
-
origin: { kind: 'portal' },
|
|
338
|
-
actorSubject: identity.subject,
|
|
339
|
-
admit: () => admitBusinessMutation(res, authorized.scope),
|
|
340
|
-
});
|
|
341
|
-
if (result === undefined)
|
|
342
|
-
return;
|
|
343
|
-
if (result.disposition === 'conflict')
|
|
344
|
-
return idempotencyConflict(res);
|
|
345
|
-
if (result.disposition === 'paused') {
|
|
346
|
-
return sendJson(res, 503, {
|
|
347
|
-
error: 'Record creation requires an active application.',
|
|
348
|
-
code: 'application_unavailable',
|
|
349
|
-
});
|
|
350
|
-
}
|
|
351
|
-
return sendJson(res, result.disposition === 'created' ? 201 : 200, {
|
|
352
|
-
ok: true,
|
|
353
|
-
data: { record: recordToWire(result.record) },
|
|
354
|
-
});
|
|
355
|
-
}
|
|
356
|
-
if (ref.recordId !== undefined && req.method === 'GET') {
|
|
357
|
-
const authorized = await requireInstallationPermission(res, ref, identity, 'records:read', deps);
|
|
358
|
-
if (authorized === undefined)
|
|
359
|
-
return;
|
|
360
|
-
const definition = enabledCollection(res, authorized.installation, collection);
|
|
361
|
-
if (definition === undefined)
|
|
362
|
-
return;
|
|
363
|
-
if (definition.authority.authority === 'external') {
|
|
364
|
-
const loaded = await loadExternalRecord(authorized.installation, definition, ref.recordId, deps);
|
|
365
|
-
if (loaded === undefined)
|
|
366
|
-
return sendJson(res, 503, { error: 'collection source unavailable' });
|
|
367
|
-
if (loaded.record === undefined)
|
|
368
|
-
return sendJson(res, 404, { error: 'record not found' });
|
|
369
|
-
return sendJson(res, 200, {
|
|
370
|
-
ok: true,
|
|
371
|
-
data: {
|
|
372
|
-
record: externalRecordToWire(loaded.record, loaded.binding),
|
|
373
|
-
collection: collectionToWire(definition),
|
|
374
|
-
},
|
|
375
|
-
});
|
|
376
|
-
}
|
|
377
|
-
const record = await deps.store.getRequest(authorized.installation.scope, collection, ref.recordId);
|
|
378
|
-
if (record === undefined)
|
|
379
|
-
return sendJson(res, 404, { error: 'record not found' });
|
|
380
|
-
return sendJson(res, 200, {
|
|
381
|
-
ok: true,
|
|
382
|
-
data: recordDetailToWire(authorized.installation, record),
|
|
383
|
-
});
|
|
384
|
-
}
|
|
385
|
-
if (ref.recordId !== undefined && req.method === 'PATCH') {
|
|
386
|
-
const body = await readJsonBody(req, deps.maxBody);
|
|
387
|
-
if (!body.ok)
|
|
388
|
-
return sendJson(res, body.status, { error: body.error });
|
|
389
|
-
const parsed = ManagedRecordMutationRequestSchema.safeParse(body.value);
|
|
390
|
-
if (!parsed.success)
|
|
391
|
-
return invalid(res, parsed.error);
|
|
392
|
-
const permission = mutationPermission(parsed.data.operation);
|
|
393
|
-
const authorized = await requireInstallationPermission(res, ref, identity, permission, deps);
|
|
394
|
-
if (authorized === undefined)
|
|
395
|
-
return;
|
|
396
|
-
const definition = enabledCollection(res, authorized.installation, collection);
|
|
397
|
-
if (definition === undefined)
|
|
398
|
-
return;
|
|
399
|
-
if (definition.authority.authority === 'external') {
|
|
400
|
-
return unsupportedExternalOperation(res, parsed.data.operation);
|
|
401
|
-
}
|
|
402
|
-
if (parsed.data.operation === 'migrate-schema') {
|
|
403
|
-
const result = await deps.store.migrateLegacyRequest({
|
|
404
|
-
scope: authorized.installation.scope,
|
|
405
|
-
collectionKey: collection,
|
|
406
|
-
id: ref.recordId,
|
|
407
|
-
expectedRevision: parsed.data.expectedRevision,
|
|
408
|
-
actorSubject: identity.subject,
|
|
409
|
-
});
|
|
410
|
-
if (!result.ok)
|
|
411
|
-
return mutationFailure(res, result);
|
|
412
|
-
return sendJson(res, 200, { ok: true, data: { record: recordToWire(result.record) } });
|
|
413
|
-
}
|
|
414
|
-
let operation;
|
|
415
|
-
if (parsed.data.operation === 'update') {
|
|
416
|
-
operation = {
|
|
417
|
-
kind: 'update',
|
|
418
|
-
payload: parsed.data.patch,
|
|
419
|
-
...(parsed.data.unset ? { unset: parsed.data.unset } : {}),
|
|
420
|
-
};
|
|
421
|
-
}
|
|
422
|
-
else if (parsed.data.operation === 'assign') {
|
|
423
|
-
if (parsed.data.assigneeSubject !== null) {
|
|
424
|
-
const assigneeGrant = await deps.store.getGrant(authorized.installation.scope, parsed.data.assigneeSubject);
|
|
425
|
-
if (assigneeGrant === undefined ||
|
|
426
|
-
assigneeGrant.revokedAt !== undefined ||
|
|
427
|
-
assigneeGrant.role === 'viewer') {
|
|
428
|
-
return sendJson(res, 422, {
|
|
429
|
-
error: 'assignee must have an active operator grant',
|
|
430
|
-
code: 'invalid_assignee',
|
|
431
|
-
});
|
|
432
|
-
}
|
|
433
|
-
}
|
|
434
|
-
operation = {
|
|
435
|
-
kind: 'assign',
|
|
436
|
-
assigneeSubject: parsed.data.assigneeSubject ?? undefined,
|
|
437
|
-
};
|
|
438
|
-
}
|
|
439
|
-
else if (parsed.data.operation === 'set-status') {
|
|
440
|
-
operation = { kind: 'set_status', status: parsed.data.status };
|
|
441
|
-
}
|
|
442
|
-
else {
|
|
443
|
-
operation = { kind: 'add_note', note: parsed.data.note };
|
|
444
|
-
}
|
|
445
|
-
let result;
|
|
446
|
-
try {
|
|
447
|
-
result = await deps.store.mutateRequest({
|
|
448
|
-
scope: authorized.installation.scope,
|
|
449
|
-
collectionKey: collection,
|
|
450
|
-
id: ref.recordId,
|
|
451
|
-
expectedRevision: parsed.data.expectedRevision,
|
|
452
|
-
actorSubject: identity.subject,
|
|
453
|
-
operation,
|
|
454
|
-
});
|
|
455
|
-
}
|
|
456
|
-
catch (error) {
|
|
457
|
-
if (error instanceof PayloadValidationError) {
|
|
458
|
-
return sendJson(res, 400, { error: error.message, code: error.code });
|
|
459
|
-
}
|
|
460
|
-
throw error;
|
|
461
|
-
}
|
|
462
|
-
if (!result.ok)
|
|
463
|
-
return mutationFailure(res, result);
|
|
464
|
-
return sendJson(res, 200, { ok: true, data: { record: recordToWire(result.record) } });
|
|
465
|
-
}
|
|
466
|
-
if (ref.recordId !== undefined && req.method === 'DELETE') {
|
|
467
|
-
const authorized = await requireInstallationPermission(res, ref, identity, 'records:delete', deps);
|
|
468
|
-
if (authorized === undefined)
|
|
469
|
-
return;
|
|
470
|
-
const definition = enabledCollection(res, authorized.installation, collection);
|
|
471
|
-
if (definition === undefined)
|
|
472
|
-
return;
|
|
473
|
-
const body = await readJsonBody(req, deps.maxBody);
|
|
474
|
-
if (!body.ok)
|
|
475
|
-
return sendJson(res, body.status, { error: body.error });
|
|
476
|
-
const revision = expectedRevision(body.value);
|
|
477
|
-
if (revision === undefined) {
|
|
478
|
-
return sendJson(res, 400, { error: 'expectedRevision must be a positive integer' });
|
|
479
|
-
}
|
|
480
|
-
if (definition.authority.authority === 'external') {
|
|
481
|
-
const loaded = await loadExternalRecord(authorized.installation, definition, ref.recordId, deps);
|
|
482
|
-
if (loaded === undefined)
|
|
483
|
-
return sendJson(res, 503, { error: 'collection source unavailable' });
|
|
484
|
-
if (loaded.record === undefined)
|
|
485
|
-
return sendJson(res, 404, { error: 'record not found' });
|
|
486
|
-
const { record } = loaded;
|
|
487
|
-
if (record.revision !== revision) {
|
|
488
|
-
return sendJson(res, 409, {
|
|
489
|
-
error: 'record revision conflict',
|
|
490
|
-
code: 'revision_conflict',
|
|
491
|
-
currentRevision: record.revision,
|
|
492
|
-
});
|
|
493
|
-
}
|
|
494
|
-
await deps.sourceStore?.suppressExternalRecord({
|
|
495
|
-
...sourceBindingKey(authorized.installation, definition),
|
|
496
|
-
sourceId: record.source.id,
|
|
497
|
-
reason: 'customer_request',
|
|
498
|
-
now: now(deps),
|
|
499
|
-
});
|
|
500
|
-
const deletedAt = now(deps).toISOString();
|
|
501
|
-
return sendJson(res, 200, {
|
|
502
|
-
ok: true,
|
|
503
|
-
data: {
|
|
504
|
-
recordId: record.id,
|
|
505
|
-
authority: 'external',
|
|
506
|
-
disposition: 'suppressed',
|
|
507
|
-
deletedAt,
|
|
508
|
-
},
|
|
509
|
-
});
|
|
510
|
-
}
|
|
511
|
-
const result = await deps.store.deleteRequest({
|
|
512
|
-
scope: authorized.installation.scope,
|
|
513
|
-
collectionKey: collection,
|
|
514
|
-
id: ref.recordId,
|
|
515
|
-
expectedRevision: revision,
|
|
516
|
-
actorSubject: identity.subject,
|
|
517
|
-
reason: 'customer_request',
|
|
518
|
-
});
|
|
519
|
-
if (!result.ok)
|
|
520
|
-
return mutationFailure(res, result);
|
|
521
|
-
return sendJson(res, 200, {
|
|
522
|
-
ok: true,
|
|
523
|
-
data: {
|
|
524
|
-
recordId: result.record.id,
|
|
525
|
-
authority: 'native',
|
|
526
|
-
disposition: 'deleted',
|
|
527
|
-
deletedAt: result.record.deletedAt,
|
|
528
|
-
},
|
|
529
|
-
});
|
|
530
|
-
}
|
|
531
|
-
return methodNotAllowed(res);
|
|
532
|
-
}
|
|
533
|
-
export async function requireIdentity(req, res, deps) {
|
|
534
|
-
return authorizeBusinessApi(req, res, deps);
|
|
535
|
-
}
|
|
536
|
-
export async function requireInstallationGrant(res, ref, identity, deps, permission) {
|
|
537
|
-
if (ref.installationId === undefined)
|
|
538
|
-
return undefined;
|
|
539
|
-
const installation = await deps.store.getInstallationById(ref.org, ref.installationId);
|
|
540
|
-
if (installation === undefined) {
|
|
541
|
-
sendJson(res, 404, { error: 'installation not found' });
|
|
542
|
-
return undefined;
|
|
543
|
-
}
|
|
544
|
-
const grant = await deps.store.getGrant(installation.scope, identity.subject);
|
|
545
|
-
if (grant?.revokedAt !== undefined || grant === undefined) {
|
|
546
|
-
sendForbidden(res, 'business grant required');
|
|
547
|
-
return undefined;
|
|
548
|
-
}
|
|
549
|
-
if (permission && !businessGrantAllows(grant, permission)) {
|
|
550
|
-
sendForbidden(res, `business permission required: ${permission}`);
|
|
551
|
-
return undefined;
|
|
552
|
-
}
|
|
553
|
-
if (!(await admitBusinessTarget(res, installation.scope)))
|
|
554
|
-
return undefined;
|
|
555
|
-
return { installation, scope: installation.scope, grant };
|
|
556
|
-
}
|
|
557
|
-
export async function requireInstallationPermission(res, ref, identity, permission, deps) {
|
|
558
|
-
return requireInstallationGrant(res, ref, identity, deps, permission);
|
|
559
|
-
}
|
|
214
|
+
export { requireIdentity, requireInstallationGrant, requireInstallationPermission, } from './business-information-access.js';
|
|
215
|
+
export { handleManagedRecords } from './business-information-records.js';
|
|
560
216
|
export function mutationFailure(res, result) {
|
|
561
217
|
const status = result.reason === 'not_found'
|
|
562
218
|
? 404
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { readJsonBody, sendJson } from '@noodle-borg/transport-http';
|
|
2
|
+
import { NativeRecordLifecycleMigrateRequestSchema, NativeRecordLifecyclePreviewResponseSchema, NativeRecordLifecycleResponseSchema, } from '@noodle-borg/wire-contracts';
|
|
3
|
+
import { NativeLifecycleError } from '../business-information/native-record-lifecycle.js';
|
|
4
|
+
import { invalid, methodNotAllowed, requireIdentity, requireInstallationPermission, } from './business-information.js';
|
|
5
|
+
export async function handleNativeRecordLifecycle(req, res, ref, deps) {
|
|
6
|
+
res.setHeader('cache-control', 'private, no-store');
|
|
7
|
+
if (req.method !== 'GET' && req.method !== 'POST')
|
|
8
|
+
return methodNotAllowed(res);
|
|
9
|
+
const identity = await requireIdentity(req, res, deps);
|
|
10
|
+
if (identity === false)
|
|
11
|
+
return;
|
|
12
|
+
const authorized = await requireInstallationPermission(res, ref, identity, 'installation:administer', deps);
|
|
13
|
+
if (!authorized)
|
|
14
|
+
return;
|
|
15
|
+
try {
|
|
16
|
+
if (req.method === 'GET') {
|
|
17
|
+
const data = await deps.store.nativeLifecycle.preview(authorized.scope, identity.subject);
|
|
18
|
+
return sendJson(res, 200, NativeRecordLifecyclePreviewResponseSchema.parse({ ok: true, data }));
|
|
19
|
+
}
|
|
20
|
+
const body = await readJsonBody(req, deps.maxBody);
|
|
21
|
+
if (!body.ok)
|
|
22
|
+
return sendJson(res, body.status, { error: body.error });
|
|
23
|
+
const parsed = NativeRecordLifecycleMigrateRequestSchema.safeParse(body.value);
|
|
24
|
+
if (!parsed.success)
|
|
25
|
+
return invalid(res, parsed.error);
|
|
26
|
+
const data = await deps.store.nativeLifecycle.migrate({
|
|
27
|
+
scope: authorized.scope,
|
|
28
|
+
actor: identity.subject,
|
|
29
|
+
preview: parsed.data.preview,
|
|
30
|
+
});
|
|
31
|
+
return sendJson(res, 200, NativeRecordLifecycleResponseSchema.parse({ ok: true, data }));
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
if (!(error instanceof NativeLifecycleError))
|
|
35
|
+
throw error;
|
|
36
|
+
return sendJson(res, error.code === 'lifecycle_denied' ? 403 : error.code === 'lifecycle_conflict' ? 409 : 503, {
|
|
37
|
+
code: error.code,
|
|
38
|
+
error: error.code === 'lifecycle_conflict'
|
|
39
|
+
? 'The reviewed inventory changed or expired. Review again before applying the migration.'
|
|
40
|
+
: error.code === 'lifecycle_denied'
|
|
41
|
+
? 'Current Owner or Admin permission is required.'
|
|
42
|
+
: 'Native record lifecycle is unavailable.',
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=business-native-lifecycle.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { readJsonBody, sendJson } from '@noodle-borg/transport-http';
|
|
2
|
-
import { BusinessWorkspaceAcceptRequestSchema, BusinessWorkspaceInvitationRequestSchema, BusinessWorkspaceIssuedInvitationResponseSchema, BusinessWorkspaceMutationResponseSchema, BusinessWorkspaceResponseSchema, BusinessWorkspaceRevisionRequestSchema, BusinessWorkspaceRoleChangeRequestSchema, } from '@noodle-borg/wire-contracts';
|
|
2
|
+
import { BusinessWorkspaceAcceptRequestSchema, BusinessWorkspaceInvitationRequestSchema, BusinessWorkspaceIssuedInvitationResponseSchema, BusinessWorkspaceListResponseSchema, BusinessWorkspaceMutationResponseSchema, BusinessWorkspaceResponseSchema, BusinessWorkspaceRevisionRequestSchema, BusinessWorkspaceRoleChangeRequestSchema, } from '@noodle-borg/wire-contracts';
|
|
3
3
|
import { admitBusinessTarget, authorizeBusinessApi } from '../business-api-admission.js';
|
|
4
4
|
import { BusinessWorkspaceError } from '../business-workspaces/contracts.js';
|
|
5
5
|
import { businessWorkspaceMethod, parseBusinessWorkspacePath, } from '../business-workspaces/paths.js';
|
|
@@ -30,6 +30,19 @@ export async function handleBusinessWorkspaceRoute(req, res, url, deps) {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
async function handle(req, res, url, deps) {
|
|
33
|
+
if (url.pathname === '/v1/me/business-workspaces') {
|
|
34
|
+
const identity = await authorizeBusinessApi(req, res, deps);
|
|
35
|
+
if (!identity)
|
|
36
|
+
return;
|
|
37
|
+
if (req.method !== 'GET') {
|
|
38
|
+
res.setHeader('allow', 'GET');
|
|
39
|
+
return sendJson(res, 405, { error: 'method not allowed' });
|
|
40
|
+
}
|
|
41
|
+
if (new Set(url.searchParams.keys()).size !== [...url.searchParams].length)
|
|
42
|
+
return invalid(res);
|
|
43
|
+
const data = await deps.workspaces.listForSubject(identity.subject, Object.fromEntries(url.searchParams));
|
|
44
|
+
return sendJson(res, 200, BusinessWorkspaceListResponseSchema.parse({ ok: true, data }));
|
|
45
|
+
}
|
|
33
46
|
const ref = parseBusinessWorkspacePath(url.pathname);
|
|
34
47
|
if (!ref)
|
|
35
48
|
return sendJson(res, 404, { error: 'not found' });
|
|
@@ -309,6 +309,7 @@ export function createServiceHandler(registry, options = {}) {
|
|
|
309
309
|
pageServiceUrl: options.publicBaseUrl,
|
|
310
310
|
...(whatsapp ? { readWhatsApp: whatsapp.projection.bind(whatsapp) } : {}),
|
|
311
311
|
store: businessInformationStore,
|
|
312
|
+
...(options.businessAuthoring ? { workspaces: options.businessAuthoring.workspaces } : {}),
|
|
312
313
|
...(businessOnboarding ? { businessOnboarding } : {}),
|
|
313
314
|
activateInstallation,
|
|
314
315
|
readInstallationActivation,
|
|
@@ -30,7 +30,9 @@ export function deploymentWebConnector(artifact, tenant, deploymentId, service)
|
|
|
30
30
|
}, call.caller).allow,
|
|
31
31
|
anonymous: call.caller === undefined || call.caller.identityKind === 'anonymous',
|
|
32
32
|
...(call.caller === undefined ? {} : { subject: call.caller.subject }),
|
|
33
|
-
...(call.publicAdmission === undefined
|
|
33
|
+
...(call.publicAdmission?.network === undefined
|
|
34
|
+
? {}
|
|
35
|
+
: { network: call.publicAdmission.network }),
|
|
34
36
|
budget: call.capabilityBudget,
|
|
35
37
|
...(call.signal === undefined ? {} : { signal: call.signal }),
|
|
36
38
|
});
|
|
@@ -37,10 +37,11 @@
|
|
|
37
37
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
+
"@noodle-borg/authoring": "0.0.0",
|
|
40
41
|
"@noodle-borg/managed-capabilities": "0.0.0",
|
|
41
42
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
42
43
|
"@noodle-borg/admission-limits": "0.0.0",
|
|
43
|
-
"@noodle-borg/agent-kit": "0.
|
|
44
|
+
"@noodle-borg/agent-kit": "0.107.0",
|
|
44
45
|
"@noodle-borg/app-package": "0.0.0",
|
|
45
46
|
"@noodle-borg/assistant-gateway": "0.0.0",
|
|
46
47
|
"@noodle-borg/auth": "0.0.0",
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const ApplicationDraftValidationResponseSchema: z.ZodObject<{
|
|
3
|
+
ok: z.ZodLiteral<true>;
|
|
4
|
+
data: z.ZodObject<{
|
|
5
|
+
validation: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
6
|
+
status: z.ZodLiteral<"valid">;
|
|
7
|
+
compilerDigest: z.ZodString;
|
|
8
|
+
artifactDigest: z.ZodString;
|
|
9
|
+
issues: z.ZodArray<z.ZodNever>;
|
|
10
|
+
draftId: z.ZodString;
|
|
11
|
+
revision: z.ZodNumber;
|
|
12
|
+
sourceDigest: z.ZodString;
|
|
13
|
+
check: z.ZodLiteral<"source-and-manifest">;
|
|
14
|
+
published: z.ZodLiteral<false>;
|
|
15
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
16
|
+
status: z.ZodLiteral<"invalid">;
|
|
17
|
+
issues: z.ZodArray<z.ZodObject<{
|
|
18
|
+
code: z.ZodString;
|
|
19
|
+
message: z.ZodString;
|
|
20
|
+
path: z.ZodOptional<z.ZodString>;
|
|
21
|
+
}, z.core.$strict>>;
|
|
22
|
+
draftId: z.ZodString;
|
|
23
|
+
revision: z.ZodNumber;
|
|
24
|
+
sourceDigest: z.ZodString;
|
|
25
|
+
check: z.ZodLiteral<"source-and-manifest">;
|
|
26
|
+
published: z.ZodLiteral<false>;
|
|
27
|
+
}, z.core.$strict>], "status">;
|
|
28
|
+
}, z.core.$strict>;
|
|
29
|
+
}, z.core.$strict>;
|
|
30
|
+
export declare const ApplicationDraftValidationClientResponseSchema: z.ZodObject<{
|
|
31
|
+
ok: z.ZodLiteral<true>;
|
|
32
|
+
data: z.ZodObject<{
|
|
33
|
+
validation: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
34
|
+
status: z.ZodLiteral<"valid">;
|
|
35
|
+
compilerDigest: z.ZodString;
|
|
36
|
+
artifactDigest: z.ZodString;
|
|
37
|
+
issues: z.ZodArray<z.ZodNever>;
|
|
38
|
+
draftId: z.ZodString;
|
|
39
|
+
revision: z.ZodNumber;
|
|
40
|
+
sourceDigest: z.ZodString;
|
|
41
|
+
check: z.ZodLiteral<"source-and-manifest">;
|
|
42
|
+
published: z.ZodLiteral<false>;
|
|
43
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
44
|
+
status: z.ZodLiteral<"invalid">;
|
|
45
|
+
issues: z.ZodArray<z.ZodObject<{
|
|
46
|
+
code: z.ZodString;
|
|
47
|
+
message: z.ZodString;
|
|
48
|
+
path: z.ZodOptional<z.ZodString>;
|
|
49
|
+
}, z.core.$strict>>;
|
|
50
|
+
draftId: z.ZodString;
|
|
51
|
+
revision: z.ZodNumber;
|
|
52
|
+
sourceDigest: z.ZodString;
|
|
53
|
+
check: z.ZodLiteral<"source-and-manifest">;
|
|
54
|
+
published: z.ZodLiteral<false>;
|
|
55
|
+
}, z.core.$strict>], "status">;
|
|
56
|
+
}, z.core.$strict>;
|
|
57
|
+
}, z.core.$strict>;
|
|
58
|
+
export type ApplicationDraftValidation = z.infer<typeof ApplicationDraftValidationResponseSchema>['data']['validation'];
|
|
59
|
+
//# sourceMappingURL=application-draft-validation.d.ts.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ApplicationDraftIdSchema } from './application-drafts.js';
|
|
3
|
+
/** A source check is transient evidence, never a stored publication/activation receipt. */
|
|
4
|
+
function response(additive) {
|
|
5
|
+
const object = additive ? z.object : z.strictObject;
|
|
6
|
+
const common = {
|
|
7
|
+
draftId: ApplicationDraftIdSchema,
|
|
8
|
+
revision: z.number().int().min(1).max(2147483647),
|
|
9
|
+
sourceDigest: z.string().regex(/^[a-f0-9]{64}$/),
|
|
10
|
+
check: z.literal('source-and-manifest'),
|
|
11
|
+
published: z.literal(false),
|
|
12
|
+
};
|
|
13
|
+
const validation = z.discriminatedUnion('status', [
|
|
14
|
+
object({
|
|
15
|
+
...common,
|
|
16
|
+
status: z.literal('valid'),
|
|
17
|
+
compilerDigest: z.string().regex(/^sha256:[a-f0-9]{64}$/),
|
|
18
|
+
artifactDigest: z.string().regex(/^[a-f0-9]{64}$/),
|
|
19
|
+
issues: z.array(z.never()).max(0),
|
|
20
|
+
}),
|
|
21
|
+
object({
|
|
22
|
+
...common,
|
|
23
|
+
status: z.literal('invalid'),
|
|
24
|
+
issues: z
|
|
25
|
+
.array(object({
|
|
26
|
+
code: z.string().regex(/^[a-z][a-z0-9_]{0,79}$/),
|
|
27
|
+
message: z.string().max(500),
|
|
28
|
+
path: z.string().max(240).optional(),
|
|
29
|
+
}))
|
|
30
|
+
.min(1)
|
|
31
|
+
.max(20),
|
|
32
|
+
}),
|
|
33
|
+
]);
|
|
34
|
+
return object({ ok: z.literal(true), data: object({ validation }) });
|
|
35
|
+
}
|
|
36
|
+
export const ApplicationDraftValidationResponseSchema = response(false);
|
|
37
|
+
export const ApplicationDraftValidationClientResponseSchema = response(true);
|
|
38
|
+
//# sourceMappingURL=application-draft-validation.js.map
|