@lucern/mcp 0.3.0-alpha.11 → 0.3.0-alpha.13

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/gateway.js CHANGED
@@ -2,6 +2,9 @@ import { z } from 'zod';
2
2
  import { v } from 'convex/values';
3
3
  import { basename, extname } from 'path';
4
4
  import { randomUUID } from 'crypto';
5
+ import { anyApi } from 'convex/server';
6
+ import { ConvexHttpClient } from 'convex/browser';
7
+ import { Permit } from 'permitio';
5
8
 
6
9
  // ../contracts/src/types/reasoning-method.ts
7
10
  var REASONING_METHODS = [
@@ -1030,6 +1033,35 @@ defineTable({
1030
1033
  { kind: "index", name: "by_source", columns: ["source"] }
1031
1034
  ]
1032
1035
  });
1036
+ defineTable({
1037
+ name: "domainEvents",
1038
+ component: "kernel",
1039
+ category: "events",
1040
+ shape: z.object({
1041
+ "eventId": z.string(),
1042
+ "type": z.string(),
1043
+ "version": z.string(),
1044
+ "timestamp": z.number(),
1045
+ "tenantId": z.string().optional(),
1046
+ "workspaceId": z.string().optional(),
1047
+ "topicId": z.string(),
1048
+ "resourceId": z.string(),
1049
+ "resourceType": z.string(),
1050
+ "actorId": z.string(),
1051
+ "actorType": z.enum(["human", "agent", "service"]),
1052
+ "data": z.record(z.any()),
1053
+ "correlationId": z.string().optional(),
1054
+ "expiresAt": z.number()
1055
+ }),
1056
+ indices: [
1057
+ { kind: "index", name: "by_eventId", columns: ["eventId"] },
1058
+ { kind: "index", name: "by_topic_timestamp", columns: ["topicId", "timestamp"] },
1059
+ { kind: "index", name: "by_tenant_workspace_timestamp", columns: ["tenantId", "workspaceId", "timestamp"] },
1060
+ { kind: "index", name: "by_type_timestamp", columns: ["type", "timestamp"] },
1061
+ { kind: "index", name: "by_resource", columns: ["resourceType", "resourceId", "timestamp"] },
1062
+ { kind: "index", name: "by_expiresAt", columns: ["expiresAt"] }
1063
+ ]
1064
+ });
1033
1065
  defineTable({
1034
1066
  name: "beliefConfidence",
1035
1067
  component: "kernel",
@@ -4328,7 +4360,9 @@ var permitObjectType = z.enum([
4328
4360
  "group",
4329
4361
  "resource_instance",
4330
4362
  "relationship_tuple",
4331
- "role_assignment"
4363
+ "role_assignment",
4364
+ "attribute_binding",
4365
+ "policy_bundle"
4332
4366
  ]);
4333
4367
  var permitOutboxOperation = z.enum([
4334
4368
  "upsert",
@@ -4434,7 +4468,10 @@ defineTable({
4434
4468
  }),
4435
4469
  indices: [
4436
4470
  { kind: "index", name: "by_principalId", columns: ["principalId"] },
4471
+ { kind: "index", name: "by_provider_subject", columns: ["provider", "providerSubjectId"] },
4472
+ { kind: "index", name: "by_provider_project_subject", columns: ["provider", "providerProjectId", "providerSubjectId"] },
4437
4473
  { kind: "index", name: "by_tenant_provider_subject", columns: ["tenantId", "provider", "providerSubjectId"] },
4474
+ { kind: "index", name: "by_tenant_provider_project_subject", columns: ["tenantId", "provider", "providerProjectId", "providerSubjectId"] },
4438
4475
  {
4439
4476
  kind: "index",
4440
4477
  name: "by_tenant_provider_alias",
@@ -9407,7 +9444,7 @@ var IDENTITY_WHOAMI = {
9407
9444
  description: "Canonical identity summary for the current session",
9408
9445
  fields: {
9409
9446
  principalId: "string \u2014 canonical federated principal identifier",
9410
- principalType: "string \u2014 human, service, or agent",
9447
+ principalType: "string \u2014 human, service, agent, group, or external_viewer",
9411
9448
  tenantId: "string | undefined \u2014 resolved tenant scope",
9412
9449
  workspaceId: "string | undefined \u2014 resolved workspace scope",
9413
9450
  scopes: "string[] | undefined \u2014 granted scopes for this session",
@@ -9418,6 +9455,49 @@ var IDENTITY_WHOAMI = {
9418
9455
  ontologyPrimitive: "identity",
9419
9456
  tier: "workhorse"
9420
9457
  };
9458
+ var RESOLVE_INTERACTIVE_PRINCIPAL = {
9459
+ name: "resolve_interactive_principal",
9460
+ description: "Read the Permit-backed Lucern principal context for an authenticated Clerk user. Like `git config --get user.email` plus the repository ACL \u2014 resolves the identity alias into the canonical authorization subject.",
9461
+ parameters: {
9462
+ clerkId: {
9463
+ type: "string",
9464
+ description: "Authenticated Clerk subject (`sub`). Clerk proves identity only; it is not the authorization record."
9465
+ },
9466
+ tenantId: {
9467
+ type: "string",
9468
+ description: "Optional tenant scope. Omit only when the Clerk alias is globally unambiguous."
9469
+ },
9470
+ workspaceId: {
9471
+ type: "string",
9472
+ description: "Optional workspace scope. Required when the principal has access to multiple workspaces and no default can be inferred."
9473
+ },
9474
+ providerProjectId: {
9475
+ type: "string",
9476
+ description: "Optional Clerk project or provider instance id for tenants with multiple identity providers."
9477
+ }
9478
+ },
9479
+ required: ["clerkId"],
9480
+ response: {
9481
+ description: "Permit-backed Lucern principal context for tenant SDK bootstrap",
9482
+ fields: {
9483
+ principalId: "string \u2014 canonical Lucern principal identifier",
9484
+ principalType: "string \u2014 human, service, agent, group, or external_viewer",
9485
+ clerkId: "string \u2014 authenticated Clerk subject alias",
9486
+ tenantId: "string \u2014 resolved tenant scope",
9487
+ workspaceId: "string | null \u2014 resolved workspace scope",
9488
+ roles: "string[] \u2014 effective Permit roles",
9489
+ scopes: "string[] \u2014 effective scopes derived from Permit/control-plane projection",
9490
+ groupIds: "string[] \u2014 active Permit group memberships",
9491
+ principalStatus: "string \u2014 active, invited, suspended, disabled, revoked, or missing",
9492
+ tenantStatus: "string \u2014 projected tenant resource status",
9493
+ workspaceStatus: "string \u2014 projected workspace resource status",
9494
+ permit: "object \u2014 Permit subject, tenant, and optional workspace tuple"
9495
+ }
9496
+ },
9497
+ ownerModule: "control-plane",
9498
+ ontologyPrimitive: "identity",
9499
+ tier: "workhorse"
9500
+ };
9421
9501
  var COMPILE_CONTEXT = {
9422
9502
  name: "compile_context",
9423
9503
  description: "Compile a focused reasoning context. If topicId is omitted, Lucern resolves the best topic from the query. Like `git log --graph --decorate` for the reasoning substrate \u2014 returns the canonical Pillar 3 context pack through the public API shape.",
@@ -11320,6 +11400,7 @@ var MCP_TOOL_CONTRACTS = {
11320
11400
  update_worktree_targets: UPDATE_WORKTREE_TARGETS,
11321
11401
  update_worktree_metadata: UPDATE_WORKTREE_METADATA,
11322
11402
  identity_whoami: IDENTITY_WHOAMI,
11403
+ resolve_interactive_principal: RESOLVE_INTERACTIVE_PRINCIPAL,
11323
11404
  compile_context: COMPILE_CONTEXT,
11324
11405
  record_scope_learning: RECORD_SCOPE_LEARNING,
11325
11406
  pipeline_snapshot: PIPELINE_SNAPSHOT,
@@ -11437,6 +11518,7 @@ function entries(names, surfaceClass, surfaceIntent, surfaces, rationale) {
11437
11518
  var MCP_CORE_OPERATION_NAMES = [
11438
11519
  "compile_context",
11439
11520
  "identity_whoami",
11521
+ "resolve_interactive_principal",
11440
11522
  "check_permission",
11441
11523
  "filter_by_permission",
11442
11524
  "create_belief",
@@ -11990,7 +12072,13 @@ function surfaceContract(args) {
11990
12072
  scopes: args.scopes ?? [
11991
12073
  args.kind === "query" ? `${args.domain}.read` : `${args.domain}.write`
11992
12074
  ],
11993
- allowedPrincipalTypes: ["user", "service", "agent"]
12075
+ allowedPrincipalTypes: [
12076
+ "user",
12077
+ "service",
12078
+ "agent",
12079
+ "group",
12080
+ "external_viewer"
12081
+ ]
11994
12082
  },
11995
12083
  convex: args.convex,
11996
12084
  gateway: args.gateway,
@@ -12132,8 +12220,6 @@ var contextContracts = [
12132
12220
  args: observationContextArgs
12133
12221
  })
12134
12222
  ];
12135
-
12136
- // ../contracts/src/function-registry/identity.ts
12137
12223
  var withPrincipal = (input, context) => ({
12138
12224
  ...input,
12139
12225
  tenantId: input.tenantId ?? context.tenantId,
@@ -12159,6 +12245,28 @@ var identityContracts = [
12159
12245
  inputProjection: withPrincipal
12160
12246
  }
12161
12247
  }),
12248
+ surfaceContract({
12249
+ name: "resolve_interactive_principal",
12250
+ kind: "query",
12251
+ domain: "controlPlane",
12252
+ surfaceClass: "platform_public",
12253
+ method: "POST",
12254
+ path: "/control-plane/identity/resolve-interactive-principal",
12255
+ sdkNamespace: "controlPlane.identity",
12256
+ sdkMethod: "resolveInteractivePrincipal",
12257
+ summary: "Resolve an authenticated Clerk user into a Permit-backed Lucern principal context.",
12258
+ args: z.object({
12259
+ clerkId: z.string().min(1),
12260
+ tenantId: z.string().min(1).optional(),
12261
+ workspaceId: z.string().min(1).optional(),
12262
+ providerProjectId: z.string().min(1).optional()
12263
+ }),
12264
+ convex: {
12265
+ module: "identity",
12266
+ functionName: "resolveInteractivePrincipal",
12267
+ kind: "query"
12268
+ }
12269
+ }),
12162
12270
  surfaceContract({
12163
12271
  name: "check_permission",
12164
12272
  kind: "query",
@@ -16251,6 +16359,13 @@ var TENANT_BOOTSTRAP_TABLE_REQUIREMENTS = [
16251
16359
  copyMode: "none",
16252
16360
  description: "Deliberation sessions are created by tenant workflows."
16253
16361
  },
16362
+ {
16363
+ component: "kernel",
16364
+ table: "domainEvents",
16365
+ prepopulation: "runtime_log",
16366
+ copyMode: "none",
16367
+ description: "Domain event rows are append-only runtime audit/exhaust data."
16368
+ },
16254
16369
  {
16255
16370
  component: "kernel",
16256
16371
  table: "epistemicAudit",
@@ -23080,23 +23195,31 @@ async function resolveTaskEventTopicId(authContext, task, operation) {
23080
23195
  });
23081
23196
  }
23082
23197
  async function emitTaskEventFromGatewayAuth(authContext, args) {
23083
- return emitDomainEvent(
23084
- (reference, input) => authContext.convex.mutation(reference, input),
23085
- {
23086
- tenantId: authContext.tenantId,
23087
- workspaceId: authContext.workspaceId,
23088
- topicId: args.topicId,
23089
- type: args.type,
23090
- resourceId: args.resourceId,
23091
- resourceType: "task",
23092
- actorId: authContext.principalId ?? authContext.userId,
23093
- actorType: inferActorType({
23094
- authMode: authContext.authMode,
23095
- principalType: authContext.principalType
23096
- }),
23097
- data: args.data
23098
- }
23099
- );
23198
+ return authContext.convex.mutation(api.events.recordEvent, {
23199
+ tenantId: authContext.tenantId,
23200
+ workspaceId: authContext.workspaceId,
23201
+ topicId: args.topicId,
23202
+ type: args.type,
23203
+ resourceId: args.resourceId,
23204
+ resourceType: "task",
23205
+ actorId: authContext.principalId ?? authContext.userId,
23206
+ actorType: inferActorType({
23207
+ authMode: authContext.authMode,
23208
+ principalType: authContext.principalType
23209
+ }),
23210
+ data: args.data
23211
+ });
23212
+ }
23213
+ async function emitTaskEventBestEffortFromGatewayAuth(authContext, args) {
23214
+ try {
23215
+ await emitTaskEventFromGatewayAuth(authContext, args);
23216
+ } catch (error) {
23217
+ console.warn("[tasks] Task write succeeded but event emission failed.", {
23218
+ taskId: args.resourceId,
23219
+ eventType: args.type,
23220
+ error: error instanceof Error ? error.message : String(error)
23221
+ });
23222
+ }
23100
23223
  }
23101
23224
  function gatewayIdempotencyArgs(authContext, options) {
23102
23225
  {
@@ -23193,7 +23316,7 @@ async function createTaskFromGatewayAuth(authContext, input, options) {
23193
23316
  ...input,
23194
23317
  topicId: resolvedTopic.topicId
23195
23318
  });
23196
- await emitTaskEventFromGatewayAuth(authContext, {
23319
+ await emitTaskEventBestEffortFromGatewayAuth(authContext, {
23197
23320
  topicId: payload.topicId ?? resolvedTopic.topicId,
23198
23321
  type: "task.created",
23199
23322
  resourceId: payload.id,
@@ -23221,7 +23344,7 @@ async function updateTaskFromGatewayAuth(authContext, input, options) {
23221
23344
  payload,
23222
23345
  "update"
23223
23346
  );
23224
- await emitTaskEventFromGatewayAuth(authContext, {
23347
+ await emitTaskEventBestEffortFromGatewayAuth(authContext, {
23225
23348
  topicId,
23226
23349
  type: "task.updated",
23227
23350
  resourceId: payload.id,
@@ -23248,7 +23371,7 @@ async function completeTaskFromGatewayAuth(authContext, input, options) {
23248
23371
  payload,
23249
23372
  "complete"
23250
23373
  );
23251
- await emitTaskEventFromGatewayAuth(authContext, {
23374
+ await emitTaskEventBestEffortFromGatewayAuth(authContext, {
23252
23375
  topicId,
23253
23376
  type: "task.completed",
23254
23377
  resourceId: payload.id,
@@ -25728,7 +25851,7 @@ function handleEventsError(error, fallbackMessage, correlationId, policyTraceId)
25728
25851
  }
25729
25852
  async function handleEventsList(args) {
25730
25853
  try {
25731
- const payload = await args.authContext.convex.query("events:listEvents", {
25854
+ const payload = await args.authContext.convex.query(api.events.listEvents, {
25732
25855
  tenantId: args.authContext.tenantId,
25733
25856
  workspaceId: args.authContext.workspaceId,
25734
25857
  topicId: args.query.topicId,
@@ -25754,7 +25877,7 @@ async function handleEventsList(args) {
25754
25877
  async function handleEventsReplay(args) {
25755
25878
  try {
25756
25879
  const payload = await args.authContext.convex.mutation(
25757
- "events:replayEvents",
25880
+ api.events.replayEvents,
25758
25881
  {
25759
25882
  tenantId: args.authContext.tenantId,
25760
25883
  workspaceId: args.authContext.workspaceId,
@@ -27032,155 +27155,1452 @@ async function handleOntologyMatch(args) {
27032
27155
  }
27033
27156
  }
27034
27157
 
27035
- // ../../apps/gateway/src/routes/questions.ts
27158
+ // ../server-core/src/auth/credentials.ts
27159
+ function parseAuthorizationBearer(value) {
27160
+ if (!value) return null;
27161
+ const [scheme, token] = value.trim().split(/\s+/, 2);
27162
+ if (!scheme || !token) return null;
27163
+ if (scheme.toLowerCase() !== "bearer") return null;
27164
+ return token.trim() || null;
27165
+ }
27166
+
27167
+ // ../../apps/gateway/src/routes/permit-webhook.ts
27168
+ var mcApi = anyApi;
27169
+ var mcClientCache = {
27170
+ value: null
27171
+ };
27172
+ function readString27(value) {
27173
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
27174
+ }
27036
27175
  function asRecord25(value) {
27037
27176
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
27038
27177
  }
27039
- function readString27(value) {
27040
- if (typeof value !== "string") {
27041
- return void 0;
27042
- }
27043
- const normalized = value.trim();
27044
- return normalized.length > 0 ? normalized : void 0;
27178
+ function readSecret(env = process.env) {
27179
+ return readString27(env.LUCERN_PERMIT_WEBHOOK_SECRET) ?? readString27(env.PERMIT_WEBHOOK_SECRET);
27045
27180
  }
27046
- function readNumber18(value) {
27047
- return typeof value === "number" && Number.isFinite(value) ? value : void 0;
27181
+ function isPermitWebhookAuthorized(args) {
27182
+ const expected = readSecret(args.env);
27183
+ if (!expected) {
27184
+ return false;
27185
+ }
27186
+ const bearer = parseAuthorizationBearer(args.headers.get("authorization"));
27187
+ const headerSecret = readString27(
27188
+ args.headers.get("x-lucern-permit-webhook-secret")
27189
+ );
27190
+ return bearer === expected || headerSecret === expected;
27048
27191
  }
27049
- function readStringArray14(value) {
27050
- if (!Array.isArray(value)) {
27051
- return void 0;
27192
+ function readTenantKeyFromValue(value) {
27193
+ if (typeof value === "string" && value.trim()) {
27194
+ return value.trim();
27052
27195
  }
27053
- const items = value.map((entry) => readString27(entry)).filter((entry) => Boolean(entry));
27054
- return items.length > 0 ? items : void 0;
27196
+ const record = asRecord25(value);
27197
+ return readString27(record.key) ?? readString27(record.tenant) ?? readString27(record.tenantKey) ?? readString27(record.tenant_id);
27055
27198
  }
27056
- async function handleQuestionCreate(args) {
27057
- try {
27058
- const body = asRecord25(args.body);
27059
- const payload = await createQuestionFromGatewayAuth(args.authContext, {
27060
- topicId: readString27(body.topicId),
27061
- text: readString27(body.text) ?? "",
27062
- priority: readString27(body.priority),
27063
- linkedBeliefId: readString27(body.linkedBeliefId),
27064
- metadata: asRecord25(body.metadata)
27065
- });
27066
- return successResponse(payload, {
27067
- status: 201,
27068
- correlationId: args.correlationId,
27069
- policyTraceId: args.policyTraceId
27070
- });
27071
- } catch (error) {
27072
- const resolved = resolveServerCoreError(error, "Failed to create question.");
27073
- return errorResponse({
27074
- code: resolved.code,
27075
- message: resolved.message,
27076
- status: resolved.status,
27077
- correlationId: args.correlationId,
27078
- policyTraceId: args.policyTraceId,
27079
- invariant: resolved.invariant,
27080
- suggestion: resolved.suggestion,
27081
- details: resolved.details
27082
- });
27199
+ function hasTenantIdentifier(value) {
27200
+ if (typeof value === "string" && value.trim()) {
27201
+ return true;
27083
27202
  }
27203
+ const record = asRecord25(value);
27204
+ return Boolean(
27205
+ readString27(record.key) ?? readString27(record.tenant) ?? readString27(record.tenantKey) ?? readString27(record.tenant_key) ?? readString27(record.tenant_id) ?? readString27(record.id)
27206
+ );
27084
27207
  }
27085
- async function handleQuestionGet(args) {
27086
- try {
27087
- const payload = await getQuestionFromGatewayAuth(
27088
- args.authContext,
27089
- args.questionId
27208
+ function extractPermitWebhookTenantKeys(body) {
27209
+ const record = asRecord25(body);
27210
+ const candidates = [
27211
+ record.tenant,
27212
+ record.tenantKey,
27213
+ record.tenant_key,
27214
+ asRecord25(record.data).tenant,
27215
+ asRecord25(record.data).tenantKey,
27216
+ asRecord25(record.data).tenant_key,
27217
+ asRecord25(record.object).tenant,
27218
+ asRecord25(record.object).tenantKey,
27219
+ asRecord25(record.object).tenant_key,
27220
+ asRecord25(record.resource_instance).tenant,
27221
+ asRecord25(record.resource_instance).tenantKey,
27222
+ asRecord25(record.resource_instance).tenant_key,
27223
+ asRecord25(record.access_request_details).tenant,
27224
+ asRecord25(record.access_request_details).tenantKey,
27225
+ asRecord25(record.access_request_details).tenant_key,
27226
+ asRecord25(asRecord25(record.data).access_request_details).tenant,
27227
+ asRecord25(asRecord25(record.data).access_request_details).tenantKey,
27228
+ asRecord25(asRecord25(record.data).access_request_details).tenant_key
27229
+ ];
27230
+ const tenantKeys = candidates.map(readTenantKeyFromValue).filter((entry) => Boolean(entry));
27231
+ return [...new Set(tenantKeys)];
27232
+ }
27233
+ function hasPermitWebhookTenantScope(body) {
27234
+ const record = asRecord25(body);
27235
+ const candidates = [
27236
+ record.tenant,
27237
+ record.tenantKey,
27238
+ record.tenant_key,
27239
+ record.tenant_id,
27240
+ asRecord25(record.data).tenant,
27241
+ asRecord25(record.data).tenantKey,
27242
+ asRecord25(record.data).tenant_key,
27243
+ asRecord25(record.data).tenant_id,
27244
+ asRecord25(record.object).tenant,
27245
+ asRecord25(record.object).tenantKey,
27246
+ asRecord25(record.object).tenant_key,
27247
+ asRecord25(record.object).tenant_id,
27248
+ asRecord25(record.resource_instance).tenant,
27249
+ asRecord25(record.resource_instance).tenantKey,
27250
+ asRecord25(record.resource_instance).tenant_key,
27251
+ asRecord25(record.resource_instance).tenant_id,
27252
+ asRecord25(record.access_request_details).tenant,
27253
+ asRecord25(record.access_request_details).tenantKey,
27254
+ asRecord25(record.access_request_details).tenant_key,
27255
+ asRecord25(record.access_request_details).tenant_id,
27256
+ asRecord25(asRecord25(record.data).access_request_details).tenant,
27257
+ asRecord25(asRecord25(record.data).access_request_details).tenantKey,
27258
+ asRecord25(asRecord25(record.data).access_request_details).tenant_key,
27259
+ asRecord25(asRecord25(record.data).access_request_details).tenant_id
27260
+ ];
27261
+ return candidates.some(hasTenantIdentifier);
27262
+ }
27263
+ function summarizePermitWebhookEvent(body) {
27264
+ const record = asRecord25(body);
27265
+ return {
27266
+ type: readString27(record.type) ?? readString27(record.event) ?? "permit.webhook",
27267
+ id: readString27(record.id) ?? readString27(record.event_id),
27268
+ tenantKeys: extractPermitWebhookTenantKeys(record)
27269
+ };
27270
+ }
27271
+ function getMasterControlConvexClient() {
27272
+ if (mcClientCache.value) {
27273
+ return mcClientCache.value;
27274
+ }
27275
+ const convexUrl = readString27(process.env.CONVEX_MC_URL);
27276
+ const deployKey = readString27(process.env.CONVEX_MC_DEPLOY_KEY);
27277
+ if (!convexUrl || !deployKey) {
27278
+ throw new GatewayAuthError(
27279
+ 503,
27280
+ "UPSTREAM_ERROR",
27281
+ "Master Control is not configured. Set CONVEX_MC_URL and CONVEX_MC_DEPLOY_KEY."
27090
27282
  );
27091
- return successResponse(payload, {
27092
- correlationId: args.correlationId,
27093
- policyTraceId: args.policyTraceId
27094
- });
27095
- } catch (error) {
27096
- const resolved = resolveServerCoreError(error, "Failed to read question.");
27097
- return errorResponse({
27098
- code: resolved.code,
27099
- message: resolved.message,
27100
- status: resolved.status,
27101
- correlationId: args.correlationId,
27102
- policyTraceId: args.policyTraceId,
27103
- invariant: resolved.invariant,
27104
- suggestion: resolved.suggestion,
27105
- details: resolved.details
27106
- });
27107
27283
  }
27284
+ const client = new ConvexHttpClient(convexUrl);
27285
+ client.setAdminAuth(
27286
+ deployKey
27287
+ );
27288
+ mcClientCache.value = client;
27289
+ return client;
27108
27290
  }
27109
- async function handleQuestionArchive(args) {
27110
- try {
27111
- const body = asRecord25(args.body);
27112
- const payload = await archiveQuestionFromGatewayAuth(args.authContext, {
27113
- id: args.questionId,
27114
- rationale: readString27(body.reason) ?? readString27(body.rationale)
27115
- });
27116
- return successResponse(payload, {
27291
+ function handlePermitWebhookError(error, correlationId, policyTraceId) {
27292
+ const resolved = resolveServerCoreError(
27293
+ error,
27294
+ "Failed to reconcile Permit projection."
27295
+ );
27296
+ return errorResponse({
27297
+ code: resolved.code,
27298
+ message: resolved.message,
27299
+ status: resolved.status,
27300
+ correlationId,
27301
+ policyTraceId,
27302
+ invariant: resolved.invariant,
27303
+ suggestion: resolved.suggestion,
27304
+ details: resolved.details
27305
+ });
27306
+ }
27307
+ async function handlePermitProjectionWebhook(args) {
27308
+ if (!readSecret()) {
27309
+ return errorResponse({
27310
+ status: 503,
27311
+ code: "INTERNAL_ERROR",
27312
+ message: "Permit webhook secret is not configured.",
27117
27313
  correlationId: args.correlationId,
27118
27314
  policyTraceId: args.policyTraceId
27119
27315
  });
27120
- } catch (error) {
27121
- const resolved = resolveServerCoreError(error, "Failed to archive question.");
27316
+ }
27317
+ if (!isPermitWebhookAuthorized({ headers: args.request.headers })) {
27122
27318
  return errorResponse({
27123
- code: resolved.code,
27124
- message: resolved.message,
27125
- status: resolved.status,
27319
+ status: 401,
27320
+ code: "AUTH_REQUIRED",
27321
+ message: "Permit webhook secret did not match.",
27126
27322
  correlationId: args.correlationId,
27127
- policyTraceId: args.policyTraceId,
27128
- invariant: resolved.invariant,
27129
- suggestion: resolved.suggestion,
27130
- details: resolved.details
27323
+ policyTraceId: args.policyTraceId
27131
27324
  });
27132
27325
  }
27133
- }
27134
- async function handleQuestionList(args) {
27135
27326
  try {
27136
- const payload = await listQuestionsFromGatewayAuth(args.authContext, args.query);
27137
- return successResponse(payload, {
27138
- correlationId: args.correlationId,
27139
- policyTraceId: args.policyTraceId
27140
- });
27327
+ const event = summarizePermitWebhookEvent(args.body);
27328
+ const tenantKeys = extractPermitWebhookTenantKeys(args.body);
27329
+ const hasTenantScope = hasPermitWebhookTenantScope(args.body);
27330
+ if (tenantKeys.length === 0 && !hasTenantScope) {
27331
+ return successResponse(
27332
+ {
27333
+ acknowledged: true,
27334
+ reconciled: false,
27335
+ reason: "No tenant key found; skipping tenant-scoped reconcile.",
27336
+ tenantKeys: []
27337
+ },
27338
+ {
27339
+ correlationId: args.correlationId,
27340
+ policyTraceId: args.policyTraceId
27341
+ }
27342
+ );
27343
+ }
27344
+ const client = args.convexClient ?? getMasterControlConvexClient();
27345
+ const receipt = await client.action(mcApi.permitProjectionActions.reconcile, {
27346
+ mode: "apply",
27347
+ trigger: "permit_webhook",
27348
+ tenantKeys: tenantKeys.length > 0 ? tenantKeys : void 0,
27349
+ environments: ["dev", "staging", "prod"],
27350
+ componentPath: "controlPlane",
27351
+ webhookSecret: readSecret(),
27352
+ event
27353
+ });
27354
+ return successResponse(
27355
+ {
27356
+ reconciled: true,
27357
+ receipt
27358
+ },
27359
+ {
27360
+ correlationId: args.correlationId,
27361
+ policyTraceId: args.policyTraceId
27362
+ }
27363
+ );
27141
27364
  } catch (error) {
27142
- const resolved = resolveServerCoreError(error, "Failed to list questions.");
27143
- return errorResponse({
27144
- code: resolved.code,
27145
- message: resolved.message,
27146
- status: resolved.status,
27147
- correlationId: args.correlationId,
27148
- policyTraceId: args.policyTraceId,
27149
- invariant: resolved.invariant,
27150
- suggestion: resolved.suggestion,
27151
- details: resolved.details
27152
- });
27365
+ return handlePermitWebhookError(
27366
+ error,
27367
+ args.correlationId,
27368
+ args.policyTraceId
27369
+ );
27153
27370
  }
27154
27371
  }
27155
- async function handleQuestionAnswer(args) {
27156
- try {
27157
- const body = asRecord25(args.body);
27158
- const payload = await answerQuestionFromGatewayAuth(args.authContext, {
27159
- id: args.questionId,
27160
- text: readString27(body.text) ?? "",
27161
- confidence: readString27(body.confidence),
27162
- evidenceIds: readStringArray14(body.evidenceIds),
27163
- rationale: readString27(body.rationale)
27164
- });
27165
- return successResponse(payload, {
27166
- correlationId: args.correlationId,
27167
- policyTraceId: args.policyTraceId
27168
- });
27169
- } catch (error) {
27170
- const resolved = resolveServerCoreError(error, "Failed to answer question.");
27171
- return errorResponse({
27172
- code: resolved.code,
27173
- message: resolved.message,
27174
- status: resolved.status,
27175
- correlationId: args.correlationId,
27176
- policyTraceId: args.policyTraceId,
27177
- invariant: resolved.invariant,
27178
- suggestion: resolved.suggestion,
27179
- details: resolved.details
27180
- });
27372
+ var mcApi2 = anyApi;
27373
+ var mcClientCache2 = {
27374
+ value: null
27375
+ };
27376
+ var permitClientCache = {
27377
+ value: null
27378
+ };
27379
+ var permitClientFactory = null;
27380
+ var SYSTEM_ACTOR_ID = "clerk:system";
27381
+ var SIGNATURE_TOLERANCE_SECONDS = 300;
27382
+ var USER_EVENTS = /* @__PURE__ */ new Set([
27383
+ "user.created",
27384
+ "user.updated",
27385
+ "user.deleted"
27386
+ ]);
27387
+ var MEMBERSHIP_EVENTS = /* @__PURE__ */ new Set([
27388
+ "organizationMembership.created",
27389
+ "organizationMembership.updated",
27390
+ "organizationMembership.deleted"
27391
+ ]);
27392
+ var INVITATION_EVENTS = /* @__PURE__ */ new Set([
27393
+ "organizationInvitation.created",
27394
+ "organizationInvitation.accepted",
27395
+ "organizationInvitation.revoked"
27396
+ ]);
27397
+ var ORGANIZATION_LIFECYCLE_EVENTS = /* @__PURE__ */ new Set([
27398
+ "organization.created",
27399
+ "organization.updated",
27400
+ "organization.deleted"
27401
+ ]);
27402
+ var PERMIT_MEMBERSHIP_ROLES = /* @__PURE__ */ new Set([
27403
+ "tenant_admin",
27404
+ "viewer",
27405
+ "editor",
27406
+ "auditor",
27407
+ "service_agent",
27408
+ "platform_admin",
27409
+ "workspace_admin"
27410
+ ]);
27411
+ var CLERK_WEBHOOK_SECRETS = [
27412
+ "LUCERN_CLERK_WEBHOOK_SECRET",
27413
+ "CLERK_WEBHOOK_SECRET",
27414
+ "CLERK_WEBHOOK_SIGNING_SECRET"
27415
+ ];
27416
+ function isRecord8(value) {
27417
+ return value !== null && typeof value === "object" && !Array.isArray(value);
27418
+ }
27419
+ function readString28(value) {
27420
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
27421
+ }
27422
+ function readNumber18(value) {
27423
+ if (typeof value === "number" && Number.isFinite(value)) {
27424
+ return value;
27425
+ }
27426
+ if (typeof value === "string" && value.trim()) {
27427
+ const parsed = Number(value);
27428
+ return Number.isFinite(parsed) ? parsed : void 0;
27181
27429
  }
27430
+ return void 0;
27182
27431
  }
27183
- async function handleQuestionGetAnswer(args) {
27432
+ var PERMIT_USER_KEY_PATTERN = /^[A-Za-z0-9|@+\-._]+$/;
27433
+ var PERMIT_USER_KEY_ESCAPE_SENTINEL = "|";
27434
+ function asRecord26(value) {
27435
+ return isRecord8(value) ? value : {};
27436
+ }
27437
+ function asArray(value) {
27438
+ return Array.isArray(value) ? value : [];
27439
+ }
27440
+ function encodeBase64(bytes) {
27441
+ const buffer = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
27442
+ let binary = "";
27443
+ for (const value of buffer) {
27444
+ binary += String.fromCharCode(value);
27445
+ }
27446
+ return btoa(binary);
27447
+ }
27448
+ function permitUserKeyForPrincipalId(principalId) {
27449
+ const trimmed = principalId.trim();
27450
+ if (PERMIT_USER_KEY_PATTERN.test(trimmed) && !trimmed.includes(PERMIT_USER_KEY_ESCAPE_SENTINEL)) {
27451
+ return trimmed;
27452
+ }
27453
+ return Array.from(trimmed).map(
27454
+ (character) => PERMIT_USER_KEY_PATTERN.test(character) && character !== PERMIT_USER_KEY_ESCAPE_SENTINEL ? character : `${PERMIT_USER_KEY_ESCAPE_SENTINEL}${character.codePointAt(0)?.toString(16) ?? "0"}${PERMIT_USER_KEY_ESCAPE_SENTINEL}`
27455
+ ).join("");
27456
+ }
27457
+ function compactRecord5(value) {
27458
+ return Object.fromEntries(
27459
+ Object.entries(value).filter(([, entry]) => entry !== void 0)
27460
+ );
27461
+ }
27462
+ function statusCodeFromError(error) {
27463
+ if (!error || typeof error !== "object") {
27464
+ return void 0;
27465
+ }
27466
+ const record = error;
27467
+ return numericStatus(record.status) ?? numericStatus(record.statusCode) ?? numericStatus(record.response?.status) ?? numericStatus(record.cause?.response?.status);
27468
+ }
27469
+ function numericStatus(value) {
27470
+ if (typeof value === "number" && Number.isFinite(value)) {
27471
+ return value;
27472
+ }
27473
+ if (typeof value === "string") {
27474
+ const parsed = Number(value);
27475
+ return Number.isFinite(parsed) ? parsed : void 0;
27476
+ }
27477
+ return void 0;
27478
+ }
27479
+ function isNotFound(error) {
27480
+ return statusCodeFromError(error) === 404 || String(error?.message ?? "").includes("404");
27481
+ }
27482
+ function isConflict(error) {
27483
+ return statusCodeFromError(error) === 409 || String(error?.message ?? "").includes("409");
27484
+ }
27485
+ function readRoleAssignments(value) {
27486
+ if (!Array.isArray(value)) {
27487
+ const record = isRecord8(value) ? value : {};
27488
+ if (Array.isArray(record.data)) {
27489
+ return record.data.filter(isRecord8);
27490
+ }
27491
+ if (Array.isArray(record.results)) {
27492
+ return record.results.filter(isRecord8);
27493
+ }
27494
+ return [];
27495
+ }
27496
+ return value.filter(isRecord8);
27497
+ }
27498
+ function roleAssignmentResourceInstance(assignment) {
27499
+ return readString28(assignment.resource_instance) ?? readString28(assignment.resourceInstance) ?? readString28(assignment.resource_instance_id) ?? readString28(assignment.resourceInstanceId);
27500
+ }
27501
+ function isTenantScopedRoleAssignment(assignment) {
27502
+ return !roleAssignmentResourceInstance(assignment);
27503
+ }
27504
+ function createPermitClient() {
27505
+ const token = readString28(process.env.LUCERN_PERMIT_API_KEY) ?? readString28(process.env.PERMIT_API_KEY);
27506
+ const pdpUrl = readString28(process.env.LUCERN_PERMIT_PDP_URL) ?? readString28(process.env.PERMIT_PDP_URL);
27507
+ const apiUrl = readString28(process.env.LUCERN_PERMIT_API_URL) ?? readString28(process.env.PERMIT_API_URL);
27508
+ if (!token || !pdpUrl) {
27509
+ throw {
27510
+ status: 502,
27511
+ code: "UPSTREAM_ERROR",
27512
+ message: "Permit projection is not configured. Set LUCERN_PERMIT_API_KEY and LUCERN_PERMIT_PDP_URL."
27513
+ };
27514
+ }
27515
+ return new Permit({
27516
+ token,
27517
+ pdp: pdpUrl,
27518
+ ...apiUrl ? { apiUrl } : {},
27519
+ throwOnError: true
27520
+ });
27521
+ }
27522
+ function getPermitClient() {
27523
+ if (permitClientCache.value) {
27524
+ return permitClientCache.value;
27525
+ }
27526
+ if (permitClientFactory) {
27527
+ permitClientCache.value = permitClientFactory();
27528
+ return permitClientCache.value;
27529
+ }
27530
+ permitClientCache.value = createPermitClient();
27531
+ return permitClientCache.value;
27532
+ }
27533
+ var __testOnly = {
27534
+ setPermitClientFactory(factory) {
27535
+ permitClientFactory = factory;
27536
+ permitClientCache.value = null;
27537
+ }
27538
+ };
27539
+ async function upsertPermitTenant(args) {
27540
+ const permit = getPermitClient();
27541
+ const tenantPayload = {
27542
+ name: args.tenantName ?? args.tenantKey,
27543
+ attributes: compactRecord5({
27544
+ clerkOrganizationId: args.clerkOrganizationId,
27545
+ clerkOrganizationSlug: args.clerkOrganizationSlug,
27546
+ mcTenantKey: args.tenantKey,
27547
+ sourceType: "organization",
27548
+ sourceEvent: args.eventType,
27549
+ eventAt: args.eventAt,
27550
+ actorId: args.actorId
27551
+ })
27552
+ };
27553
+ try {
27554
+ return await permit.api.tenants.update(args.tenantKey, tenantPayload);
27555
+ } catch (error) {
27556
+ if (!isNotFound(error)) {
27557
+ throw error;
27558
+ }
27559
+ }
27560
+ return await permit.api.tenants.create({
27561
+ key: args.tenantKey,
27562
+ ...tenantPayload
27563
+ });
27564
+ }
27565
+ async function syncPermitUser(args) {
27566
+ const permit = getPermitClient();
27567
+ return await permit.api.users.sync({
27568
+ key: permitUserKeyForPrincipalId(args.userId),
27569
+ email: args.email,
27570
+ attributes: compactRecord5({
27571
+ sourceType: "clerk_webhook_user",
27572
+ sourceEvent: args.eventType,
27573
+ clerkStatus: args.eventType,
27574
+ clerkDisplayName: args.displayName,
27575
+ eventAt: args.eventAt,
27576
+ actorId: args.actorId
27577
+ })
27578
+ });
27579
+ }
27580
+ async function upsertPermitTenantMembershipRole(args) {
27581
+ const permit = getPermitClient();
27582
+ const permitUserId = permitUserKeyForPrincipalId(args.userId);
27583
+ const existing = readRoleAssignments(
27584
+ await permit.api.roleAssignments.list({
27585
+ user: permitUserId,
27586
+ tenant: args.tenantKey,
27587
+ perPage: 100
27588
+ })
27589
+ );
27590
+ await Promise.all(
27591
+ existing.map((assignment2) => {
27592
+ const role = readString28(assignment2.role);
27593
+ if (!role || !PERMIT_MEMBERSHIP_ROLES.has(role)) {
27594
+ return Promise.resolve();
27595
+ }
27596
+ if (!isTenantScopedRoleAssignment(assignment2)) {
27597
+ return Promise.resolve();
27598
+ }
27599
+ if (role === args.role) {
27600
+ return Promise.resolve();
27601
+ }
27602
+ return unassignPermitTenantMembershipRole({
27603
+ permit,
27604
+ permitUserId,
27605
+ tenant: args.tenantKey,
27606
+ role
27607
+ });
27608
+ })
27609
+ );
27610
+ const assignment = {
27611
+ user: permitUserId,
27612
+ role: args.role,
27613
+ tenant: args.tenantKey
27614
+ };
27615
+ try {
27616
+ return await permit.api.roleAssignments.assign(assignment);
27617
+ } catch (error) {
27618
+ if (isConflict(error)) {
27619
+ return { alreadyAssigned: true };
27620
+ }
27621
+ throw error;
27622
+ }
27623
+ }
27624
+ async function unassignPermitTenantMembershipRole(args) {
27625
+ const api2 = args.permit.api;
27626
+ const assignment = {
27627
+ user: args.permitUserId,
27628
+ role: args.role,
27629
+ tenant: args.tenant,
27630
+ ...args.resourceInstance ? { resource_instance: args.resourceInstance } : {}
27631
+ };
27632
+ if (typeof api2.roleAssignments?.unassign === "function") {
27633
+ return await api2.roleAssignments.unassign(assignment);
27634
+ }
27635
+ if (typeof api2.unassignRole === "function") {
27636
+ return await api2.unassignRole(assignment);
27637
+ }
27638
+ if (typeof api2.users?.unassignRole === "function") {
27639
+ return await api2.users.unassignRole({
27640
+ user: args.permitUserId,
27641
+ role: args.role,
27642
+ tenant: args.tenant
27643
+ });
27644
+ }
27645
+ throw new Error("Permit SDK does not expose an unassignRole method");
27646
+ }
27647
+ async function revokePermitTenantMembershipRoles(args) {
27648
+ const permit = getPermitClient();
27649
+ const permitUserId = permitUserKeyForPrincipalId(args.userId);
27650
+ const assignments = readRoleAssignments(
27651
+ await permit.api.roleAssignments.list({
27652
+ user: permitUserId,
27653
+ tenant: args.tenantKey,
27654
+ perPage: 100
27655
+ })
27656
+ );
27657
+ const membershipRoles = assignments.filter(
27658
+ (assignment) => isTenantScopedRoleAssignment(assignment) && PERMIT_MEMBERSHIP_ROLES.has(readString28(assignment.role) ?? "")
27659
+ );
27660
+ await Promise.all(
27661
+ membershipRoles.map((assignment) => {
27662
+ const role = readString28(assignment.role);
27663
+ if (!role) {
27664
+ return Promise.resolve();
27665
+ }
27666
+ return unassignPermitTenantMembershipRole({
27667
+ permit,
27668
+ permitUserId,
27669
+ tenant: args.tenantKey,
27670
+ role
27671
+ });
27672
+ })
27673
+ );
27674
+ }
27675
+ function normalizeBase64(value) {
27676
+ return value.replace(/-/g, "+").replace(/_/g, "/");
27677
+ }
27678
+ function maybeBase64(value) {
27679
+ if (!value || value.length < 16) {
27680
+ return false;
27681
+ }
27682
+ if (value.length % 4 === 1) {
27683
+ return false;
27684
+ }
27685
+ return /^[A-Za-z0-9+/=_-]+$/.test(value);
27686
+ }
27687
+ function decodeBase64OrRaw(value) {
27688
+ if (!value) {
27689
+ return new Uint8Array();
27690
+ }
27691
+ const trimmed = value.trim();
27692
+ const secretMaterial = trimmed.startsWith("whsec_") ? trimmed.slice("whsec_".length) : trimmed;
27693
+ const candidate = normalizeBase64(secretMaterial);
27694
+ if (!maybeBase64(candidate)) {
27695
+ return new TextEncoder().encode(secretMaterial);
27696
+ }
27697
+ try {
27698
+ const binary = atob(candidate);
27699
+ return Uint8Array.from(binary, (entry) => entry.charCodeAt(0));
27700
+ } catch {
27701
+ return new TextEncoder().encode(secretMaterial);
27702
+ }
27703
+ }
27704
+ function readSigningSecret(env = process.env) {
27705
+ for (const key of CLERK_WEBHOOK_SECRETS) {
27706
+ const value = readString28(env[key]);
27707
+ if (value) {
27708
+ return value;
27709
+ }
27710
+ }
27711
+ return void 0;
27712
+ }
27713
+ function parseSvixSignatures(header) {
27714
+ return header.split(",").map((entry) => entry.trim()).filter(Boolean).flatMap((entry) => {
27715
+ if (entry.startsWith("v1=")) {
27716
+ return [entry.slice("v1=".length)];
27717
+ }
27718
+ return [];
27719
+ }).filter(Boolean);
27720
+ }
27721
+ function parseWebhookHeaders(headers) {
27722
+ const secret = readSigningSecret();
27723
+ const webhookId = headers.get("svix-id");
27724
+ const timestamp = headers.get("svix-timestamp");
27725
+ const signatureHeader = headers.get("svix-signature");
27726
+ if (!secret || !webhookId || !timestamp || !signatureHeader) {
27727
+ return null;
27728
+ }
27729
+ return {
27730
+ webhookId,
27731
+ timestamp,
27732
+ signatures: parseSvixSignatures(signatureHeader),
27733
+ secret
27734
+ };
27735
+ }
27736
+ function safeEquals(left, right) {
27737
+ if (left.length !== right.length) {
27738
+ return false;
27739
+ }
27740
+ let diff = 0;
27741
+ for (let index = 0; index < left.length; index += 1) {
27742
+ diff |= left.charCodeAt(index) ^ right.charCodeAt(index);
27743
+ }
27744
+ return diff === 0;
27745
+ }
27746
+ async function verifyClerkSignature(args) {
27747
+ const parsed = parseWebhookHeaders(args.headers);
27748
+ if (!parsed) {
27749
+ return "missing_headers_or_secret";
27750
+ }
27751
+ const signatureTimestamp = readNumber18(parsed.timestamp);
27752
+ if (!signatureTimestamp) {
27753
+ return "malformed_timestamp";
27754
+ }
27755
+ const nowSeconds = Math.floor(Date.now() / 1e3);
27756
+ if (Math.abs(nowSeconds - signatureTimestamp) > SIGNATURE_TOLERANCE_SECONDS) {
27757
+ return "signature_expired";
27758
+ }
27759
+ const message = `${parsed.webhookId}.${parsed.timestamp}.${args.body}`;
27760
+ const keyBytes = decodeBase64OrRaw(parsed.secret);
27761
+ const key = await crypto.subtle.importKey(
27762
+ "raw",
27763
+ keyBytes,
27764
+ { name: "HMAC", hash: "SHA-256" },
27765
+ false,
27766
+ ["sign"]
27767
+ );
27768
+ const computed = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(message));
27769
+ const computedSignature = encodeBase64(computed);
27770
+ return parsed.signatures.some((candidate) => safeEquals(candidate, computedSignature)) || "signature_mismatch";
27771
+ }
27772
+ function extractClerkActorId(payload) {
27773
+ const event = asRecord26(payload);
27774
+ const data = asRecord26(event.data);
27775
+ return readString28(event.actor_id) || readString28(asRecord26(event.actor).id) || readString28(data.actor_id) || readString28(asRecord26(data.actor).id) || readString28(data.created_by) || readString28(asRecord26(data.public_user_data).user_id) || SYSTEM_ACTOR_ID;
27776
+ }
27777
+ function extractUserData(data) {
27778
+ const user = asRecord26(data.user);
27779
+ if (Object.keys(user).length > 0) {
27780
+ return user;
27781
+ }
27782
+ const publicUser = asRecord26(data.public_user_data);
27783
+ if (Object.keys(publicUser).length > 0) {
27784
+ return publicUser;
27785
+ }
27786
+ return data;
27787
+ }
27788
+ function extractOrganizationIds(data) {
27789
+ const organization = asRecord26(data.organization);
27790
+ return {
27791
+ organizationId: readString28(data.organization_id) || readString28(data.id) || readString28(organization.id),
27792
+ organizationSlug: readString28(data.organization_slug) || readString28(data.slug) || readString28(organization.slug)
27793
+ };
27794
+ }
27795
+ function readPrimaryEmail(userData) {
27796
+ const direct = readString28(userData.primary_email_address) || readString28(userData.email) || readString28(userData.emailAddress);
27797
+ if (direct) {
27798
+ return direct;
27799
+ }
27800
+ for (const entry of asArray(userData.email_addresses)) {
27801
+ const row = asRecord26(entry);
27802
+ const value = readString28(row.email_address) || readString28(row.emailAddress) || readString28(row.address);
27803
+ if (value) {
27804
+ return value;
27805
+ }
27806
+ }
27807
+ return void 0;
27808
+ }
27809
+ function readDisplayName(userData) {
27810
+ const first = readString28(userData.first_name) || readString28(userData.firstName);
27811
+ const last = readString28(userData.last_name) || readString28(userData.lastName);
27812
+ if (first || last) {
27813
+ return [first, last].filter(Boolean).join(" ");
27814
+ }
27815
+ return readString28(userData.username) || readString28(userData.name);
27816
+ }
27817
+ function normalizeRole(value) {
27818
+ const normalized = readString28(value)?.toLowerCase() ?? "viewer";
27819
+ if (normalized === "admin" || normalized === "owner" || normalized === "org:admin") {
27820
+ return "tenant_admin";
27821
+ }
27822
+ if (normalized === "editor" || normalized === "viewer" || normalized === "auditor" || normalized === "service_agent" || normalized === "platform_admin" || normalized === "tenant_admin" || normalized === "workspace_admin") {
27823
+ return normalized;
27824
+ }
27825
+ if (normalized === "basic_member" || normalized === "org:member") {
27826
+ return "viewer";
27827
+ }
27828
+ return "viewer";
27829
+ }
27830
+ function buildWebhookMetadata(args) {
27831
+ return {
27832
+ source: "clerk_webhook",
27833
+ eventType: args.eventType,
27834
+ eventId: args.eventId,
27835
+ eventAt: args.eventAt,
27836
+ actorId: args.actorId,
27837
+ ...args.extra
27838
+ };
27839
+ }
27840
+ function extractOrganizationName(organization) {
27841
+ return readString28(organization.name) || readString28(organization.slug) || readString28(organization.title);
27842
+ }
27843
+ async function getMasterControlConvexClient2() {
27844
+ if (mcClientCache2.value) {
27845
+ return mcClientCache2.value;
27846
+ }
27847
+ const convexUrl = readString28(process.env.CONVEX_MC_URL);
27848
+ const deployKey = readString28(process.env.CONVEX_MC_DEPLOY_KEY);
27849
+ if (!convexUrl || !deployKey) {
27850
+ throw new Error(
27851
+ "Master Control is not configured. Set CONVEX_MC_URL and CONVEX_MC_DEPLOY_KEY."
27852
+ );
27853
+ }
27854
+ const client = new ConvexHttpClient(convexUrl);
27855
+ client.setAdminAuth(
27856
+ deployKey
27857
+ );
27858
+ mcClientCache2.value = client;
27859
+ return client;
27860
+ }
27861
+ async function resolveTenantByOrgSlug(args) {
27862
+ if (!args.organizationSlug) {
27863
+ return void 0;
27864
+ }
27865
+ const tenant = await args.client.query(mcApi2.tenants.getBySlug, {
27866
+ slug: args.organizationSlug
27867
+ });
27868
+ if (!tenant || !isRecord8(tenant)) {
27869
+ return void 0;
27870
+ }
27871
+ const tenantId = readString28(tenant._id);
27872
+ const tenantSlug = readString28(tenant.slug);
27873
+ if (!tenantId || !tenantSlug) {
27874
+ return void 0;
27875
+ }
27876
+ return { tenantId, tenantSlug };
27877
+ }
27878
+ function webhookError(code, status, message, correlationId, policyTraceId, details) {
27879
+ return errorResponse({
27880
+ code,
27881
+ status,
27882
+ message,
27883
+ correlationId,
27884
+ policyTraceId,
27885
+ details
27886
+ });
27887
+ }
27888
+ function handleClerkWebhookError(error, correlationId, policyTraceId) {
27889
+ const resolved = resolveServerCoreError(error, "Failed to reconcile Clerk webhook.");
27890
+ return errorResponse({
27891
+ code: resolved.code,
27892
+ message: resolved.message,
27893
+ status: resolved.status,
27894
+ correlationId,
27895
+ policyTraceId,
27896
+ invariant: resolved.invariant,
27897
+ suggestion: resolved.suggestion,
27898
+ details: resolved.details
27899
+ });
27900
+ }
27901
+ async function handleClerkWebhook(args) {
27902
+ try {
27903
+ const rawBody = await args.request.clone().text();
27904
+ const verification = await verifyClerkSignature({
27905
+ body: rawBody,
27906
+ headers: args.request.headers
27907
+ });
27908
+ if (verification !== true) {
27909
+ let message = "Clerk webhook signature verification failed.";
27910
+ if (verification === "signature_expired") {
27911
+ message = "Clerk webhook signature is too old.";
27912
+ }
27913
+ if (verification === "malformed_timestamp") {
27914
+ message = "Malformed Clerk webhook timestamp header.";
27915
+ }
27916
+ if (verification === "missing_headers_or_secret") {
27917
+ message = "Missing Clerk webhook signature headers or secret.";
27918
+ }
27919
+ return webhookError(
27920
+ "AUTH_REQUIRED",
27921
+ 401,
27922
+ message,
27923
+ args.correlationId,
27924
+ args.policyTraceId
27925
+ );
27926
+ }
27927
+ let payload;
27928
+ try {
27929
+ payload = JSON.parse(rawBody);
27930
+ } catch {
27931
+ return webhookError(
27932
+ "INVALID_REQUEST",
27933
+ 400,
27934
+ "Clerk webhook body must be valid JSON.",
27935
+ args.correlationId,
27936
+ args.policyTraceId
27937
+ );
27938
+ }
27939
+ const eventType = readString28(payload.type);
27940
+ if (!eventType) {
27941
+ return webhookError(
27942
+ "INVALID_REQUEST",
27943
+ 400,
27944
+ "Clerk webhook payload must include event type.",
27945
+ args.correlationId,
27946
+ args.policyTraceId
27947
+ );
27948
+ }
27949
+ const data = asRecord26(payload.data);
27950
+ const actorId = extractClerkActorId(payload);
27951
+ const eventId = readString28(payload.id);
27952
+ const eventTimestamp = readString28(payload.created_at) || readString28(payload.timestamp);
27953
+ const isOrgLifecycleEvent = ORGANIZATION_LIFECYCLE_EVENTS.has(eventType);
27954
+ const isUserEvent = USER_EVENTS.has(eventType);
27955
+ const isMembershipEvent = MEMBERSHIP_EVENTS.has(eventType);
27956
+ const isInvitationEvent = INVITATION_EVENTS.has(eventType);
27957
+ const getClient = async () => args.convexClient ?? await getMasterControlConvexClient2();
27958
+ if (isOrgLifecycleEvent) {
27959
+ const nestedOrganization = asRecord26(data.organization);
27960
+ const organizationRecord = Object.keys(nestedOrganization).length > 0 ? nestedOrganization : data;
27961
+ const organizationId = readString28(data.id) || readString28(data.organization_id) || readString28(organizationRecord.id);
27962
+ const organizationIds = extractOrganizationIds(data);
27963
+ if (!organizationId) {
27964
+ return webhookError(
27965
+ "INVALID_REQUEST",
27966
+ 400,
27967
+ "Clerk organization webhook payload missing organization id.",
27968
+ args.correlationId,
27969
+ args.policyTraceId
27970
+ );
27971
+ }
27972
+ const client = await getClient();
27973
+ const tenant = await resolveTenantByOrgSlug({
27974
+ client,
27975
+ organizationSlug: organizationIds.organizationSlug
27976
+ });
27977
+ if (!tenant) {
27978
+ return webhookError(
27979
+ "NOT_FOUND",
27980
+ 404,
27981
+ "Could not resolve tenant for Clerk organization webhook event.",
27982
+ args.correlationId,
27983
+ args.policyTraceId,
27984
+ {
27985
+ eventType,
27986
+ organizationId,
27987
+ organizationSlug: organizationIds.organizationSlug
27988
+ }
27989
+ );
27990
+ }
27991
+ await upsertPermitTenant({
27992
+ clerkOrganizationId: organizationId,
27993
+ clerkOrganizationSlug: organizationIds.organizationSlug,
27994
+ tenantKey: tenant.tenantSlug,
27995
+ tenantName: extractOrganizationName(organizationRecord),
27996
+ eventType,
27997
+ eventAt: eventTimestamp,
27998
+ actorId
27999
+ });
28000
+ const principal = await client.mutation(mcApi2.identity.upsertPrincipal, {
28001
+ principalId: organizationId,
28002
+ principalType: "group",
28003
+ clerkId: organizationId,
28004
+ displayName: extractOrganizationName(organizationRecord),
28005
+ status: eventType === "organization.deleted" ? "disabled" : "active",
28006
+ actorClerkId: actorId,
28007
+ tenantId: tenant.tenantId,
28008
+ metadata: buildWebhookMetadata({
28009
+ eventType,
28010
+ eventId,
28011
+ actorId,
28012
+ eventAt: eventTimestamp,
28013
+ extra: {
28014
+ sourceType: "organization",
28015
+ organizationId,
28016
+ organizationSlug: organizationIds.organizationSlug,
28017
+ organizationName: extractOrganizationName(organizationRecord),
28018
+ organizationStatus: eventType
28019
+ }
28020
+ })
28021
+ });
28022
+ const alias = await client.mutation(mcApi2.identity.upsertPrincipalIdentityAlias, {
28023
+ principalId: organizationId,
28024
+ principalRefId: void 0,
28025
+ provider: "clerk",
28026
+ providerProjectId: void 0,
28027
+ externalSubjectId: organizationId,
28028
+ tenantId: tenant.tenantId,
28029
+ email: void 0,
28030
+ metadata: buildWebhookMetadata({
28031
+ eventType,
28032
+ eventId,
28033
+ actorId,
28034
+ eventAt: eventTimestamp,
28035
+ extra: {
28036
+ sourceType: "organization",
28037
+ organizationId,
28038
+ organizationSlug: organizationIds.organizationSlug,
28039
+ organizationName: extractOrganizationName(organizationRecord),
28040
+ organizationStatus: eventType
28041
+ }
28042
+ }),
28043
+ actorClerkId: actorId
28044
+ });
28045
+ return successResponse(
28046
+ {
28047
+ acknowledged: true,
28048
+ eventType,
28049
+ tenantId: tenant.tenantId,
28050
+ principalId: organizationId,
28051
+ principal,
28052
+ alias
28053
+ },
28054
+ {
28055
+ correlationId: args.correlationId,
28056
+ policyTraceId: args.policyTraceId
28057
+ }
28058
+ );
28059
+ }
28060
+ if (isUserEvent) {
28061
+ const client = await getClient();
28062
+ const userData = extractUserData(data);
28063
+ const userId = readString28(userData.id) || readString28(data.id);
28064
+ if (!userId) {
28065
+ return webhookError(
28066
+ "INVALID_REQUEST",
28067
+ 400,
28068
+ "Clerk user webhook payload missing user id.",
28069
+ args.correlationId,
28070
+ args.policyTraceId
28071
+ );
28072
+ }
28073
+ await syncPermitUser({
28074
+ userId,
28075
+ email: readPrimaryEmail(userData),
28076
+ displayName: readDisplayName(userData),
28077
+ eventType,
28078
+ eventAt: eventTimestamp,
28079
+ actorId
28080
+ });
28081
+ const principal = await client.mutation(mcApi2.identity.upsertPrincipal, {
28082
+ principalId: userId,
28083
+ principalType: "user",
28084
+ clerkId: userId,
28085
+ email: readPrimaryEmail(userData),
28086
+ displayName: readDisplayName(userData),
28087
+ status: eventType === "user.deleted" ? "disabled" : "active",
28088
+ actorClerkId: actorId,
28089
+ metadata: buildWebhookMetadata({
28090
+ eventType,
28091
+ eventId,
28092
+ actorId,
28093
+ eventAt: eventTimestamp,
28094
+ extra: {
28095
+ userId,
28096
+ clerkStatus: eventType,
28097
+ user: userData
28098
+ }
28099
+ })
28100
+ });
28101
+ const alias = await client.mutation(mcApi2.identity.upsertPrincipalIdentityAlias, {
28102
+ principalId: userId,
28103
+ principalRefId: void 0,
28104
+ provider: "clerk",
28105
+ providerProjectId: void 0,
28106
+ externalSubjectId: userId,
28107
+ tenantId: void 0,
28108
+ email: readPrimaryEmail(userData),
28109
+ metadata: buildWebhookMetadata({
28110
+ eventType,
28111
+ eventId,
28112
+ actorId,
28113
+ eventAt: eventTimestamp,
28114
+ extra: {
28115
+ userId,
28116
+ sourceType: "user",
28117
+ status: eventType,
28118
+ email: readPrimaryEmail(userData),
28119
+ displayName: readDisplayName(userData)
28120
+ }
28121
+ }),
28122
+ actorClerkId: actorId
28123
+ });
28124
+ return successResponse(
28125
+ {
28126
+ acknowledged: true,
28127
+ eventType,
28128
+ principal,
28129
+ alias,
28130
+ source: {
28131
+ eventType,
28132
+ eventId
28133
+ }
28134
+ },
28135
+ {
28136
+ correlationId: args.correlationId,
28137
+ policyTraceId: args.policyTraceId
28138
+ }
28139
+ );
28140
+ }
28141
+ if (isMembershipEvent || isInvitationEvent) {
28142
+ const client = await getClient();
28143
+ const org = extractOrganizationIds(data);
28144
+ const tenant = await resolveTenantByOrgSlug({
28145
+ client,
28146
+ organizationSlug: org.organizationSlug
28147
+ });
28148
+ if (!tenant) {
28149
+ return webhookError(
28150
+ "NOT_FOUND",
28151
+ 404,
28152
+ "Could not resolve tenant for Clerk organization webhook event.",
28153
+ args.correlationId,
28154
+ args.policyTraceId,
28155
+ {
28156
+ eventType,
28157
+ organizationId: org.organizationId,
28158
+ organizationSlug: org.organizationSlug
28159
+ }
28160
+ );
28161
+ }
28162
+ const userId = readString28(data.user_id) || readString28(asRecord26(data.public_user_data).user_id) || readString28(asRecord26(data.user).id);
28163
+ const rawRole = readString28(data.role);
28164
+ const role = normalizeRole(rawRole);
28165
+ const permitTenantKey = tenant.tenantSlug;
28166
+ if (!permitTenantKey) {
28167
+ return webhookError(
28168
+ "INVALID_REQUEST",
28169
+ 400,
28170
+ "Clerk organization webhook payload missing organization tenant key.",
28171
+ args.correlationId,
28172
+ args.policyTraceId
28173
+ );
28174
+ }
28175
+ if (INVITATION_EVENTS.has(eventType)) {
28176
+ const invitationId = readString28(data.id);
28177
+ const invitationAccepted = eventType === "organizationInvitation.accepted";
28178
+ const invitationRevoked = eventType === "organizationInvitation.revoked";
28179
+ let fallbackInvitationStatus = "created";
28180
+ if (invitationAccepted) {
28181
+ fallbackInvitationStatus = "accepted";
28182
+ } else if (invitationRevoked) {
28183
+ fallbackInvitationStatus = "revoked";
28184
+ }
28185
+ const invitationStatus = readString28(data.status) || fallbackInvitationStatus;
28186
+ if (!invitationId) {
28187
+ return webhookError(
28188
+ "INVALID_REQUEST",
28189
+ 400,
28190
+ "Clerk organization invitation webhook payload missing invitation id.",
28191
+ args.correlationId,
28192
+ args.policyTraceId
28193
+ );
28194
+ }
28195
+ if (userId) {
28196
+ const userEmail = readPrimaryEmail(asRecord26(data.public_user_data));
28197
+ await syncPermitUser({
28198
+ userId,
28199
+ email: userEmail,
28200
+ displayName: void 0,
28201
+ eventType,
28202
+ eventAt: eventTimestamp,
28203
+ actorId
28204
+ });
28205
+ const existingPrincipal = invitationAccepted ? null : await client.query(mcApi2.identity.getPrincipalByPrincipalId, {
28206
+ principalId: userId
28207
+ });
28208
+ const principalStatus = invitationAccepted ? "active" : readString28(asRecord26(existingPrincipal).status) ?? "invited";
28209
+ await client.mutation(mcApi2.identity.upsertPrincipal, {
28210
+ principalId: userId,
28211
+ principalType: "user",
28212
+ clerkId: userId,
28213
+ actorClerkId: actorId,
28214
+ status: principalStatus,
28215
+ metadata: buildWebhookMetadata({
28216
+ eventType,
28217
+ eventId,
28218
+ actorId,
28219
+ eventAt: eventTimestamp,
28220
+ extra: {
28221
+ sourceType: "organization_invitation",
28222
+ invitationId,
28223
+ organizationId: org.organizationId,
28224
+ organizationSlug: org.organizationSlug,
28225
+ membershipId: readString28(data.membership_id),
28226
+ role,
28227
+ tenantId: tenant.tenantId
28228
+ }
28229
+ })
28230
+ });
28231
+ if (invitationAccepted) {
28232
+ await upsertPermitTenantMembershipRole({
28233
+ userId,
28234
+ tenantKey: permitTenantKey,
28235
+ role
28236
+ });
28237
+ await client.mutation(mcApi2.identity.upsertMembership, {
28238
+ principalId: userId,
28239
+ principalRefId: void 0,
28240
+ tenantId: tenant.tenantId,
28241
+ role,
28242
+ source: "api",
28243
+ actorClerkId: actorId
28244
+ });
28245
+ }
28246
+ await client.mutation(mcApi2.identity.upsertPrincipalIdentityAlias, {
28247
+ principalId: userId,
28248
+ principalRefId: void 0,
28249
+ provider: "clerk",
28250
+ providerProjectId: void 0,
28251
+ externalSubjectId: userId,
28252
+ tenantId: tenant.tenantId,
28253
+ email: readPrimaryEmail(asRecord26(data.public_user_data)),
28254
+ metadata: buildWebhookMetadata({
28255
+ eventType,
28256
+ eventId,
28257
+ actorId,
28258
+ eventAt: eventTimestamp,
28259
+ extra: {
28260
+ sourceType: "organization_invitation",
28261
+ organizationId: org.organizationId,
28262
+ organizationSlug: org.organizationSlug,
28263
+ invitationId,
28264
+ invitationStatus,
28265
+ role,
28266
+ tenantId: tenant.tenantId,
28267
+ membershipId: readString28(data.membership_id)
28268
+ }
28269
+ }),
28270
+ actorClerkId: actorId
28271
+ });
28272
+ if (invitationRevoked) {
28273
+ await revokePermitTenantMembershipRoles({
28274
+ userId,
28275
+ tenantKey: permitTenantKey
28276
+ });
28277
+ const existing = await client.query(mcApi2.identity.getMembershipForPrincipal, {
28278
+ principalId: userId,
28279
+ tenantId: tenant.tenantId,
28280
+ workspaceId: void 0
28281
+ });
28282
+ if (existing) {
28283
+ await client.mutation(mcApi2.identity.revokeMembership, {
28284
+ membershipId: existing._id,
28285
+ actorClerkId: actorId
28286
+ });
28287
+ }
28288
+ }
28289
+ }
28290
+ return successResponse(
28291
+ {
28292
+ acknowledged: true,
28293
+ eventType,
28294
+ tenantId: tenant.tenantId,
28295
+ principalId: userId,
28296
+ invitationId,
28297
+ userMatched: Boolean(userId),
28298
+ skipped: userId ? void 0 : "no_user_reference"
28299
+ },
28300
+ {
28301
+ correlationId: args.correlationId,
28302
+ policyTraceId: args.policyTraceId
28303
+ }
28304
+ );
28305
+ }
28306
+ if (!userId) {
28307
+ return webhookError(
28308
+ "INVALID_REQUEST",
28309
+ 400,
28310
+ "Clerk membership webhook payload missing user id.",
28311
+ args.correlationId,
28312
+ args.policyTraceId
28313
+ );
28314
+ }
28315
+ await syncPermitUser({
28316
+ userId,
28317
+ email: readPrimaryEmail(asRecord26(data.public_user_data)),
28318
+ displayName: void 0,
28319
+ eventType,
28320
+ eventAt: eventTimestamp,
28321
+ actorId
28322
+ });
28323
+ await client.mutation(mcApi2.identity.upsertPrincipal, {
28324
+ principalId: userId,
28325
+ principalType: "user",
28326
+ clerkId: userId,
28327
+ actorClerkId: actorId,
28328
+ status: "active",
28329
+ metadata: buildWebhookMetadata({
28330
+ eventType,
28331
+ eventId,
28332
+ actorId,
28333
+ eventAt: eventTimestamp,
28334
+ extra: {
28335
+ sourceType: "organization_membership",
28336
+ organizationId: org.organizationId,
28337
+ organizationSlug: org.organizationSlug,
28338
+ membershipId: readString28(data.id),
28339
+ role,
28340
+ tenantId: tenant.tenantId
28341
+ }
28342
+ })
28343
+ });
28344
+ await client.mutation(mcApi2.identity.upsertPrincipalIdentityAlias, {
28345
+ principalId: userId,
28346
+ principalRefId: void 0,
28347
+ provider: "clerk",
28348
+ providerProjectId: void 0,
28349
+ externalSubjectId: userId,
28350
+ tenantId: tenant.tenantId,
28351
+ email: readPrimaryEmail(asRecord26(data.public_user_data)),
28352
+ metadata: buildWebhookMetadata({
28353
+ eventType,
28354
+ eventId,
28355
+ actorId,
28356
+ eventAt: eventTimestamp,
28357
+ extra: {
28358
+ sourceType: "organization_membership",
28359
+ organizationId: org.organizationId,
28360
+ organizationSlug: org.organizationSlug,
28361
+ membershipId: readString28(data.id),
28362
+ role,
28363
+ tenantId: tenant.tenantId,
28364
+ organizationEventType: eventType
28365
+ }
28366
+ }),
28367
+ actorClerkId: actorId
28368
+ });
28369
+ if (eventType === "organizationMembership.deleted") {
28370
+ await revokePermitTenantMembershipRoles({
28371
+ userId,
28372
+ tenantKey: permitTenantKey
28373
+ });
28374
+ const existing = await client.query(mcApi2.identity.getMembershipForPrincipal, {
28375
+ principalId: userId,
28376
+ tenantId: tenant.tenantId,
28377
+ workspaceId: void 0
28378
+ });
28379
+ if (!existing) {
28380
+ return successResponse(
28381
+ {
28382
+ acknowledged: true,
28383
+ eventType,
28384
+ principalId: userId,
28385
+ tenantId: tenant.tenantId,
28386
+ skipped: "membership_not_found"
28387
+ },
28388
+ {
28389
+ correlationId: args.correlationId,
28390
+ policyTraceId: args.policyTraceId
28391
+ }
28392
+ );
28393
+ }
28394
+ const revoked = await client.mutation(mcApi2.identity.revokeMembership, {
28395
+ membershipId: existing._id,
28396
+ actorClerkId: actorId
28397
+ });
28398
+ return successResponse(
28399
+ {
28400
+ acknowledged: true,
28401
+ eventType,
28402
+ tenantId: tenant.tenantId,
28403
+ principalId: userId,
28404
+ revoked
28405
+ },
28406
+ {
28407
+ correlationId: args.correlationId,
28408
+ policyTraceId: args.policyTraceId
28409
+ }
28410
+ );
28411
+ }
28412
+ const membership = await client.mutation(mcApi2.identity.upsertMembership, {
28413
+ principalId: userId,
28414
+ principalRefId: void 0,
28415
+ tenantId: tenant.tenantId,
28416
+ role,
28417
+ source: "api",
28418
+ actorClerkId: actorId
28419
+ });
28420
+ await upsertPermitTenantMembershipRole({
28421
+ userId,
28422
+ tenantKey: permitTenantKey,
28423
+ role
28424
+ });
28425
+ return successResponse(
28426
+ {
28427
+ acknowledged: true,
28428
+ eventType,
28429
+ tenantId: tenant.tenantId,
28430
+ principalId: userId,
28431
+ membership
28432
+ },
28433
+ {
28434
+ correlationId: args.correlationId,
28435
+ policyTraceId: args.policyTraceId
28436
+ }
28437
+ );
28438
+ }
28439
+ return successResponse(
28440
+ {
28441
+ acknowledged: true,
28442
+ eventType,
28443
+ reason: "Unsupported Clerk event type"
28444
+ },
28445
+ {
28446
+ correlationId: args.correlationId,
28447
+ policyTraceId: args.policyTraceId
28448
+ }
28449
+ );
28450
+ } catch (error) {
28451
+ return handleClerkWebhookError(error, args.correlationId, args.policyTraceId);
28452
+ }
28453
+ }
28454
+
28455
+ // ../../apps/gateway/src/routes/questions.ts
28456
+ function asRecord27(value) {
28457
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
28458
+ }
28459
+ function readString29(value) {
28460
+ if (typeof value !== "string") {
28461
+ return void 0;
28462
+ }
28463
+ const normalized = value.trim();
28464
+ return normalized.length > 0 ? normalized : void 0;
28465
+ }
28466
+ function readNumber19(value) {
28467
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
28468
+ }
28469
+ function readStringArray14(value) {
28470
+ if (!Array.isArray(value)) {
28471
+ return void 0;
28472
+ }
28473
+ const items = value.map((entry) => readString29(entry)).filter((entry) => Boolean(entry));
28474
+ return items.length > 0 ? items : void 0;
28475
+ }
28476
+ async function handleQuestionCreate(args) {
28477
+ try {
28478
+ const body = asRecord27(args.body);
28479
+ const payload = await createQuestionFromGatewayAuth(args.authContext, {
28480
+ topicId: readString29(body.topicId),
28481
+ text: readString29(body.text) ?? "",
28482
+ priority: readString29(body.priority),
28483
+ linkedBeliefId: readString29(body.linkedBeliefId),
28484
+ metadata: asRecord27(body.metadata)
28485
+ });
28486
+ return successResponse(payload, {
28487
+ status: 201,
28488
+ correlationId: args.correlationId,
28489
+ policyTraceId: args.policyTraceId
28490
+ });
28491
+ } catch (error) {
28492
+ const resolved = resolveServerCoreError(error, "Failed to create question.");
28493
+ return errorResponse({
28494
+ code: resolved.code,
28495
+ message: resolved.message,
28496
+ status: resolved.status,
28497
+ correlationId: args.correlationId,
28498
+ policyTraceId: args.policyTraceId,
28499
+ invariant: resolved.invariant,
28500
+ suggestion: resolved.suggestion,
28501
+ details: resolved.details
28502
+ });
28503
+ }
28504
+ }
28505
+ async function handleQuestionGet(args) {
28506
+ try {
28507
+ const payload = await getQuestionFromGatewayAuth(
28508
+ args.authContext,
28509
+ args.questionId
28510
+ );
28511
+ return successResponse(payload, {
28512
+ correlationId: args.correlationId,
28513
+ policyTraceId: args.policyTraceId
28514
+ });
28515
+ } catch (error) {
28516
+ const resolved = resolveServerCoreError(error, "Failed to read question.");
28517
+ return errorResponse({
28518
+ code: resolved.code,
28519
+ message: resolved.message,
28520
+ status: resolved.status,
28521
+ correlationId: args.correlationId,
28522
+ policyTraceId: args.policyTraceId,
28523
+ invariant: resolved.invariant,
28524
+ suggestion: resolved.suggestion,
28525
+ details: resolved.details
28526
+ });
28527
+ }
28528
+ }
28529
+ async function handleQuestionArchive(args) {
28530
+ try {
28531
+ const body = asRecord27(args.body);
28532
+ const payload = await archiveQuestionFromGatewayAuth(args.authContext, {
28533
+ id: args.questionId,
28534
+ rationale: readString29(body.reason) ?? readString29(body.rationale)
28535
+ });
28536
+ return successResponse(payload, {
28537
+ correlationId: args.correlationId,
28538
+ policyTraceId: args.policyTraceId
28539
+ });
28540
+ } catch (error) {
28541
+ const resolved = resolveServerCoreError(error, "Failed to archive question.");
28542
+ return errorResponse({
28543
+ code: resolved.code,
28544
+ message: resolved.message,
28545
+ status: resolved.status,
28546
+ correlationId: args.correlationId,
28547
+ policyTraceId: args.policyTraceId,
28548
+ invariant: resolved.invariant,
28549
+ suggestion: resolved.suggestion,
28550
+ details: resolved.details
28551
+ });
28552
+ }
28553
+ }
28554
+ async function handleQuestionList(args) {
28555
+ try {
28556
+ const payload = await listQuestionsFromGatewayAuth(args.authContext, args.query);
28557
+ return successResponse(payload, {
28558
+ correlationId: args.correlationId,
28559
+ policyTraceId: args.policyTraceId
28560
+ });
28561
+ } catch (error) {
28562
+ const resolved = resolveServerCoreError(error, "Failed to list questions.");
28563
+ return errorResponse({
28564
+ code: resolved.code,
28565
+ message: resolved.message,
28566
+ status: resolved.status,
28567
+ correlationId: args.correlationId,
28568
+ policyTraceId: args.policyTraceId,
28569
+ invariant: resolved.invariant,
28570
+ suggestion: resolved.suggestion,
28571
+ details: resolved.details
28572
+ });
28573
+ }
28574
+ }
28575
+ async function handleQuestionAnswer(args) {
28576
+ try {
28577
+ const body = asRecord27(args.body);
28578
+ const payload = await answerQuestionFromGatewayAuth(args.authContext, {
28579
+ id: args.questionId,
28580
+ text: readString29(body.text) ?? "",
28581
+ confidence: readString29(body.confidence),
28582
+ evidenceIds: readStringArray14(body.evidenceIds),
28583
+ rationale: readString29(body.rationale)
28584
+ });
28585
+ return successResponse(payload, {
28586
+ correlationId: args.correlationId,
28587
+ policyTraceId: args.policyTraceId
28588
+ });
28589
+ } catch (error) {
28590
+ const resolved = resolveServerCoreError(error, "Failed to answer question.");
28591
+ return errorResponse({
28592
+ code: resolved.code,
28593
+ message: resolved.message,
28594
+ status: resolved.status,
28595
+ correlationId: args.correlationId,
28596
+ policyTraceId: args.policyTraceId,
28597
+ invariant: resolved.invariant,
28598
+ suggestion: resolved.suggestion,
28599
+ details: resolved.details
28600
+ });
28601
+ }
28602
+ }
28603
+ async function handleQuestionGetAnswer(args) {
27184
28604
  try {
27185
28605
  const payload = await getQuestionAnswerFromGatewayAuth(
27186
28606
  args.authContext,
@@ -27206,11 +28626,11 @@ async function handleQuestionGetAnswer(args) {
27206
28626
  }
27207
28627
  async function handleQuestionRefine(args) {
27208
28628
  try {
27209
- const body = asRecord25(args.body);
28629
+ const body = asRecord27(args.body);
27210
28630
  const payload = await refineQuestionFromGatewayAuth(args.authContext, {
27211
28631
  id: args.questionId,
27212
- text: readString27(body.text) ?? "",
27213
- rationale: readString27(body.rationale)
28632
+ text: readString29(body.text) ?? "",
28633
+ rationale: readString29(body.rationale)
27214
28634
  });
27215
28635
  return successResponse(payload, {
27216
28636
  correlationId: args.correlationId,
@@ -27232,11 +28652,11 @@ async function handleQuestionRefine(args) {
27232
28652
  }
27233
28653
  async function handleQuestionUpdateStatus(args) {
27234
28654
  try {
27235
- const body = asRecord25(args.body);
28655
+ const body = asRecord27(args.body);
27236
28656
  const payload = await updateQuestionStatusFromGatewayAuth(args.authContext, {
27237
28657
  id: args.questionId,
27238
- status: readString27(body.status) ?? "",
27239
- rationale: readString27(body.rationale)
28658
+ status: readString29(body.status) ?? "",
28659
+ rationale: readString29(body.rationale)
27240
28660
  });
27241
28661
  return successResponse(payload, {
27242
28662
  correlationId: args.correlationId,
@@ -27261,19 +28681,19 @@ async function handleQuestionUpdateStatus(args) {
27261
28681
  }
27262
28682
  async function handleQuestionBatchCreate(args) {
27263
28683
  try {
27264
- const body = asRecord25(args.body);
27265
- const questions = Array.isArray(body.questions) ? body.questions.map((entry) => asRecord25(entry)).map((entry) => ({
27266
- question: readString27(entry.question) ?? readString27(entry.text) ?? "",
27267
- category: readString27(entry.category),
27268
- priority: readString27(entry.priority),
27269
- linkedBeliefNodeId: readString27(entry.linkedBeliefNodeId) ?? readString27(entry.linkedBeliefId),
27270
- linkedWorktreeId: readString27(entry.linkedWorktreeId),
27271
- testType: readString27(entry.testType)
28684
+ const body = asRecord27(args.body);
28685
+ const questions = Array.isArray(body.questions) ? body.questions.map((entry) => asRecord27(entry)).map((entry) => ({
28686
+ question: readString29(entry.question) ?? readString29(entry.text) ?? "",
28687
+ category: readString29(entry.category),
28688
+ priority: readString29(entry.priority),
28689
+ linkedBeliefNodeId: readString29(entry.linkedBeliefNodeId) ?? readString29(entry.linkedBeliefId),
28690
+ linkedWorktreeId: readString29(entry.linkedWorktreeId),
28691
+ testType: readString29(entry.testType)
27272
28692
  })) : [];
27273
28693
  const payload = await createQuestionsBatchFromGatewayAuth(args.authContext, {
27274
- topicId: readString27(body.topicId),
28694
+ topicId: readString29(body.topicId),
27275
28695
  questions,
27276
- source: readString27(body.source)
28696
+ source: readString29(body.source)
27277
28697
  });
27278
28698
  return successResponse(payload, {
27279
28699
  status: 201,
@@ -27299,20 +28719,20 @@ async function handleQuestionBatchCreate(args) {
27299
28719
  }
27300
28720
  async function handleQuestionAdd(args) {
27301
28721
  try {
27302
- const body = asRecord25(args.body);
28722
+ const body = asRecord27(args.body);
27303
28723
  const payload = await addQuestionFromGatewayAuth(args.authContext, {
27304
- topicId: readString27(body.topicId),
27305
- question: readString27(body.question) ?? readString27(body.text),
27306
- category: readString27(body.category),
27307
- priority: readString27(body.priority),
27308
- source: readString27(body.source),
27309
- beliefId: readString27(body.beliefId) ?? readString27(body.linkedBeliefId),
27310
- linkedWorktreeId: readString27(body.linkedWorktreeId),
27311
- chatId: readString27(body.chatId),
27312
- importance: readNumber18(body.importance),
27313
- epistemicUnlock: readString27(body.epistemicUnlock),
27314
- metadata: asRecord25(body.metadata),
27315
- questionType: readString27(body.questionType)
28724
+ topicId: readString29(body.topicId),
28725
+ question: readString29(body.question) ?? readString29(body.text),
28726
+ category: readString29(body.category),
28727
+ priority: readString29(body.priority),
28728
+ source: readString29(body.source),
28729
+ beliefId: readString29(body.beliefId) ?? readString29(body.linkedBeliefId),
28730
+ linkedWorktreeId: readString29(body.linkedWorktreeId),
28731
+ chatId: readString29(body.chatId),
28732
+ importance: readNumber19(body.importance),
28733
+ epistemicUnlock: readString29(body.epistemicUnlock),
28734
+ metadata: asRecord27(body.metadata),
28735
+ questionType: readString29(body.questionType)
27316
28736
  });
27317
28737
  return successResponse(payload, {
27318
28738
  status: 201,
@@ -27335,12 +28755,12 @@ async function handleQuestionAdd(args) {
27335
28755
  }
27336
28756
  async function handleQuestionUpdatePriority(args) {
27337
28757
  try {
27338
- const body = asRecord25(args.body);
28758
+ const body = asRecord27(args.body);
27339
28759
  const payload = await updateQuestionPriorityFromGatewayAuth(
27340
28760
  args.authContext,
27341
28761
  {
27342
- id: readString27(body.id) ?? readString27(body.nodeId) ?? readString27(body.questionId),
27343
- priority: readString27(body.priority) ?? "medium"
28762
+ id: readString29(body.id) ?? readString29(body.nodeId) ?? readString29(body.questionId),
28763
+ priority: readString29(body.priority) ?? "medium"
27344
28764
  }
27345
28765
  );
27346
28766
  return successResponse(payload, {
@@ -27366,12 +28786,12 @@ async function handleQuestionUpdatePriority(args) {
27366
28786
  }
27367
28787
  async function handleQuestionAdvanceToConviction(args) {
27368
28788
  try {
27369
- const body = asRecord25(args.body);
28789
+ const body = asRecord27(args.body);
27370
28790
  const payload = await advanceQuestionToConvictionFromGatewayAuth(
27371
28791
  args.authContext,
27372
28792
  {
27373
- questionId: readString27(body.questionId) ?? readString27(body.id) ?? readString27(body.nodeId),
27374
- worktreeId: readString27(body.worktreeId)
28793
+ questionId: readString29(body.questionId) ?? readString29(body.id) ?? readString29(body.nodeId),
28794
+ worktreeId: readString29(body.worktreeId)
27375
28795
  }
27376
28796
  );
27377
28797
  return successResponse(payload, {
@@ -27397,14 +28817,14 @@ async function handleQuestionAdvanceToConviction(args) {
27397
28817
  }
27398
28818
  async function handleQuestionUpdateConviction(args) {
27399
28819
  try {
27400
- const body = asRecord25(args.body);
28820
+ const body = asRecord27(args.body);
27401
28821
  const payload = await updateQuestionConvictionFromGatewayAuth(
27402
28822
  args.authContext,
27403
28823
  {
27404
- questionId: readString27(body.questionId) ?? readString27(body.id) ?? readString27(body.nodeId),
27405
- conviction: readNumber18(body.conviction),
27406
- answerCompleteness: readString27(body.answerCompleteness),
27407
- convictionRationale: readString27(body.convictionRationale)
28824
+ questionId: readString29(body.questionId) ?? readString29(body.id) ?? readString29(body.nodeId),
28825
+ conviction: readNumber19(body.conviction),
28826
+ answerCompleteness: readString29(body.answerCompleteness),
28827
+ convictionRationale: readString29(body.convictionRationale)
27408
28828
  }
27409
28829
  );
27410
28830
  return successResponse(payload, {
@@ -27430,16 +28850,16 @@ async function handleQuestionUpdateConviction(args) {
27430
28850
  }
27431
28851
  async function handleQuestionFinalizeConviction(args) {
27432
28852
  try {
27433
- const body = asRecord25(args.body);
28853
+ const body = asRecord27(args.body);
27434
28854
  const payload = await finalizeQuestionConvictionFromGatewayAuth(
27435
28855
  args.authContext,
27436
28856
  {
27437
- questionId: readString27(body.questionId) ?? readString27(body.id) ?? readString27(body.nodeId),
27438
- conviction: readNumber18(body.conviction) ?? Number.NaN,
27439
- answer: readString27(body.answer) ?? "",
27440
- convictionRationale: readString27(body.convictionRationale),
27441
- answerCompleteness: readString27(body.answerCompleteness),
27442
- whatWeNeed: readString27(body.whatWeNeed)
28857
+ questionId: readString29(body.questionId) ?? readString29(body.id) ?? readString29(body.nodeId),
28858
+ conviction: readNumber19(body.conviction) ?? Number.NaN,
28859
+ answer: readString29(body.answer) ?? "",
28860
+ convictionRationale: readString29(body.convictionRationale),
28861
+ answerCompleteness: readString29(body.answerCompleteness),
28862
+ whatWeNeed: readString29(body.whatWeNeed)
27443
28863
  }
27444
28864
  );
27445
28865
  return successResponse(payload, {
@@ -27465,12 +28885,12 @@ async function handleQuestionFinalizeConviction(args) {
27465
28885
  }
27466
28886
  async function handleQuestionUpdate(args) {
27467
28887
  try {
27468
- const body = asRecord25(args.body);
28888
+ const body = asRecord27(args.body);
27469
28889
  const payload = await updateQuestionFromGatewayAuth(args.authContext, {
27470
- questionId: readString27(body.questionId) ?? readString27(body.id) ?? readString27(body.nodeId),
27471
- question: readString27(body.question) ?? readString27(body.text),
27472
- category: readString27(body.category),
27473
- priority: readString27(body.priority)
28890
+ questionId: readString29(body.questionId) ?? readString29(body.id) ?? readString29(body.nodeId),
28891
+ question: readString29(body.question) ?? readString29(body.text),
28892
+ category: readString29(body.category),
28893
+ priority: readString29(body.priority)
27474
28894
  });
27475
28895
  return successResponse(payload, {
27476
28896
  correlationId: args.correlationId,
@@ -27492,9 +28912,9 @@ async function handleQuestionUpdate(args) {
27492
28912
  }
27493
28913
  async function handleQuestionDelete(args) {
27494
28914
  try {
27495
- const body = asRecord25(args.body);
28915
+ const body = asRecord27(args.body);
27496
28916
  const payload = await deleteQuestionFromGatewayAuth(args.authContext, {
27497
- questionId: readString27(body.questionId) ?? readString27(body.id) ?? readString27(body.nodeId)
28917
+ questionId: readString29(body.questionId) ?? readString29(body.id) ?? readString29(body.nodeId)
27498
28918
  });
27499
28919
  return successResponse(payload, {
27500
28920
  correlationId: args.correlationId,
@@ -27516,30 +28936,30 @@ async function handleQuestionDelete(args) {
27516
28936
  }
27517
28937
 
27518
28938
  // ../../apps/gateway/src/routes/search.ts
27519
- function asRecord26(value) {
28939
+ function asRecord28(value) {
27520
28940
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
27521
28941
  }
27522
- function readString28(value) {
28942
+ function readString30(value) {
27523
28943
  if (typeof value !== "string") {
27524
28944
  return void 0;
27525
28945
  }
27526
28946
  const normalized = value.trim();
27527
28947
  return normalized.length > 0 ? normalized : void 0;
27528
28948
  }
27529
- function readNumber19(value) {
28949
+ function readNumber20(value) {
27530
28950
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
27531
28951
  }
27532
28952
  function readStringArray15(value) {
27533
28953
  if (!Array.isArray(value)) {
27534
28954
  return void 0;
27535
28955
  }
27536
- const items = value.map((entry) => readString28(entry)).filter((entry) => Boolean(entry));
28956
+ const items = value.map((entry) => readString30(entry)).filter((entry) => Boolean(entry));
27537
28957
  return items.length > 0 ? items : void 0;
27538
28958
  }
27539
28959
  async function handleSearchResources(args) {
27540
- const body = asRecord26(args.body);
27541
- const q = readString28(body.q) ?? readString28(body.query);
27542
- const topicId = readString28(body.topicId) ?? readString28(body.projectId);
28960
+ const body = asRecord28(args.body);
28961
+ const q = readString30(body.q) ?? readString30(body.query);
28962
+ const topicId = readString30(body.topicId) ?? readString30(body.projectId);
27543
28963
  if (!q) {
27544
28964
  return errorResponse({
27545
28965
  code: "INVALID_REQUEST",
@@ -27563,10 +28983,10 @@ async function handleSearchResources(args) {
27563
28983
  q,
27564
28984
  topicId,
27565
28985
  types: readStringArray15(body.types),
27566
- status: readString28(body.status),
27567
- minConfidence: readNumber19(body.minConfidence),
27568
- limit: readNumber19(body.limit),
27569
- cursor: readString28(body.cursor)
28986
+ status: readString30(body.status),
28987
+ minConfidence: readNumber20(body.minConfidence),
28988
+ limit: readNumber20(body.limit),
28989
+ cursor: readString30(body.cursor)
27570
28990
  });
27571
28991
  return successResponse(payload, {
27572
28992
  correlationId: args.correlationId,
@@ -27588,17 +29008,17 @@ async function handleSearchResources(args) {
27588
29008
  }
27589
29009
 
27590
29010
  // ../../apps/gateway/src/routes/sources.ts
27591
- function asRecord27(value) {
29011
+ function asRecord29(value) {
27592
29012
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
27593
29013
  }
27594
- function readString29(value) {
29014
+ function readString31(value) {
27595
29015
  if (typeof value !== "string") {
27596
29016
  return void 0;
27597
29017
  }
27598
29018
  const normalized = value.trim();
27599
29019
  return normalized.length > 0 ? normalized : void 0;
27600
29020
  }
27601
- function readNumber20(value) {
29021
+ function readNumber21(value) {
27602
29022
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
27603
29023
  }
27604
29024
  function handleSourcesError(error, fallbackMessage, correlationId, policyTraceId) {
@@ -27616,15 +29036,15 @@ function handleSourcesError(error, fallbackMessage, correlationId, policyTraceId
27616
29036
  }
27617
29037
  async function handleSourceUpsert(args) {
27618
29038
  try {
27619
- const body = asRecord27(args.body);
29039
+ const body = asRecord29(args.body);
27620
29040
  const payload = await upsertSourceFromGatewayAuth(args.authContext, {
27621
- url: readString29(body.url),
27622
- sha: readString29(body.sha),
27623
- kind: readString29(body.kind) ?? "",
27624
- title: readString29(body.title),
27625
- capturedAt: readNumber20(body.capturedAt),
27626
- topicId: readString29(body.topicId),
27627
- metadata: asRecord27(body.metadata)
29041
+ url: readString31(body.url),
29042
+ sha: readString31(body.sha),
29043
+ kind: readString31(body.kind) ?? "",
29044
+ title: readString31(body.title),
29045
+ capturedAt: readNumber21(body.capturedAt),
29046
+ topicId: readString31(body.topicId),
29047
+ metadata: asRecord29(body.metadata)
27628
29048
  });
27629
29049
  return successResponse(payload, {
27630
29050
  status: 201,
@@ -27658,10 +29078,10 @@ async function handleSourceGet(args) {
27658
29078
  }
27659
29079
 
27660
29080
  // ../../apps/gateway/src/routes/tasks.ts
27661
- function asRecord28(value) {
29081
+ function asRecord30(value) {
27662
29082
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
27663
29083
  }
27664
- function readString30(value) {
29084
+ function readString32(value) {
27665
29085
  if (typeof value !== "string") {
27666
29086
  return void 0;
27667
29087
  }
@@ -27683,18 +29103,18 @@ function handleTasksError(error, fallbackMessage, correlationId, policyTraceId)
27683
29103
  }
27684
29104
  async function handleTaskCreate(args) {
27685
29105
  try {
27686
- const body = asRecord28(args.body);
29106
+ const body = asRecord30(args.body);
27687
29107
  const payload = await createTaskFromGatewayAuth(args.authContext, {
27688
- topicId: readString30(body.topicId),
27689
- title: readString30(body.title) ?? "",
27690
- description: readString30(body.description),
27691
- taskType: readString30(body.taskType),
27692
- priority: readString30(body.priority),
27693
- status: readString30(body.status),
27694
- linkedBeliefId: readString30(body.linkedBeliefId),
27695
- linkedQuestionId: readString30(body.linkedQuestionId),
27696
- linkedWorktreeId: readString30(body.linkedWorktreeId),
27697
- tags: Array.isArray(body.tags) ? body.tags.map((entry) => readString30(entry)).filter((entry) => Boolean(entry)) : void 0,
29108
+ topicId: readString32(body.topicId),
29109
+ title: readString32(body.title) ?? "",
29110
+ description: readString32(body.description),
29111
+ taskType: readString32(body.taskType),
29112
+ priority: readString32(body.priority),
29113
+ status: readString32(body.status),
29114
+ linkedBeliefId: readString32(body.linkedBeliefId),
29115
+ linkedQuestionId: readString32(body.linkedQuestionId),
29116
+ linkedWorktreeId: readString32(body.linkedWorktreeId),
29117
+ tags: Array.isArray(body.tags) ? body.tags.map((entry) => readString32(entry)).filter((entry) => Boolean(entry)) : void 0,
27698
29118
  metadata: body.metadata && typeof body.metadata === "object" && !Array.isArray(body.metadata) ? body.metadata : void 0
27699
29119
  });
27700
29120
  return successResponse(payload, {
@@ -27729,16 +29149,16 @@ async function handleTaskList(args) {
27729
29149
  }
27730
29150
  async function handleTaskUpdate(args) {
27731
29151
  try {
27732
- const body = asRecord28(args.body);
29152
+ const body = asRecord30(args.body);
27733
29153
  const payload = await updateTaskFromGatewayAuth(args.authContext, {
27734
29154
  id: args.taskId,
27735
- title: readString30(body.title),
27736
- description: readString30(body.description),
27737
- priority: readString30(body.priority),
27738
- status: readString30(body.status),
27739
- linkedBeliefId: readString30(body.linkedBeliefId),
27740
- linkedQuestionId: readString30(body.linkedQuestionId),
27741
- linkedWorktreeId: readString30(body.linkedWorktreeId),
29155
+ title: readString32(body.title),
29156
+ description: readString32(body.description),
29157
+ priority: readString32(body.priority),
29158
+ status: readString32(body.status),
29159
+ linkedBeliefId: readString32(body.linkedBeliefId),
29160
+ linkedQuestionId: readString32(body.linkedQuestionId),
29161
+ linkedWorktreeId: readString32(body.linkedWorktreeId),
27742
29162
  metadata: body.metadata && typeof body.metadata === "object" && !Array.isArray(body.metadata) ? body.metadata : void 0
27743
29163
  });
27744
29164
  return successResponse(payload, {
@@ -27756,10 +29176,10 @@ async function handleTaskUpdate(args) {
27756
29176
  }
27757
29177
  async function handleTaskComplete(args) {
27758
29178
  try {
27759
- const body = asRecord28(args.body);
29179
+ const body = asRecord30(args.body);
27760
29180
  const payload = await completeTaskFromGatewayAuth(args.authContext, {
27761
29181
  id: args.taskId,
27762
- outputSummary: readString30(body.outputSummary)
29182
+ outputSummary: readString32(body.outputSummary)
27763
29183
  });
27764
29184
  return successResponse(payload, {
27765
29185
  correlationId: args.correlationId,
@@ -27776,10 +29196,10 @@ async function handleTaskComplete(args) {
27776
29196
  }
27777
29197
 
27778
29198
  // ../../apps/gateway/src/routes/topics.ts
27779
- function asRecord29(value) {
29199
+ function asRecord31(value) {
27780
29200
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
27781
29201
  }
27782
- function readString31(value) {
29202
+ function readString33(value) {
27783
29203
  if (typeof value !== "string") {
27784
29204
  return void 0;
27785
29205
  }
@@ -27789,14 +29209,14 @@ function readString31(value) {
27789
29209
  function readBoolean(value) {
27790
29210
  return typeof value === "boolean" ? value : void 0;
27791
29211
  }
27792
- function readNumber21(value) {
29212
+ function readNumber22(value) {
27793
29213
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
27794
29214
  }
27795
29215
  function readStringArray16(value) {
27796
29216
  if (!Array.isArray(value)) {
27797
29217
  return void 0;
27798
29218
  }
27799
- const items = value.map((entry) => readString31(entry)).filter((entry) => Boolean(entry));
29219
+ const items = value.map((entry) => readString33(entry)).filter((entry) => Boolean(entry));
27800
29220
  return items.length > 0 ? items : void 0;
27801
29221
  }
27802
29222
  function handleTopicsError(error, fallbackMessage, correlationId, policyTraceId) {
@@ -27814,17 +29234,17 @@ function handleTopicsError(error, fallbackMessage, correlationId, policyTraceId)
27814
29234
  }
27815
29235
  async function handleTopicCreate(args) {
27816
29236
  try {
27817
- const body = asRecord29(args.body);
29237
+ const body = asRecord31(args.body);
27818
29238
  const payload = await createTopicFromGatewayAuth(args.authContext, {
27819
- name: readString31(body.name) ?? "",
27820
- description: readString31(body.description),
27821
- type: readString31(body.type),
27822
- parentTopicId: readString31(body.parentTopicId),
27823
- ontologyId: readString31(body.ontologyId),
27824
- tenantId: readString31(body.tenantId),
27825
- workspaceId: readString31(body.workspaceId),
27826
- visibility: readString31(body.visibility),
27827
- createdBy: readString31(body.createdBy)
29239
+ name: readString33(body.name) ?? "",
29240
+ description: readString33(body.description),
29241
+ type: readString33(body.type),
29242
+ parentTopicId: readString33(body.parentTopicId),
29243
+ ontologyId: readString33(body.ontologyId),
29244
+ tenantId: readString33(body.tenantId),
29245
+ workspaceId: readString33(body.workspaceId),
29246
+ visibility: readString33(body.visibility),
29247
+ createdBy: readString33(body.createdBy)
27828
29248
  });
27829
29249
  return successResponse(payload, {
27830
29250
  status: 201,
@@ -27842,16 +29262,16 @@ async function handleTopicCreate(args) {
27842
29262
  }
27843
29263
  async function handleTopicUpdate(args) {
27844
29264
  try {
27845
- const body = asRecord29(args.body);
29265
+ const body = asRecord31(args.body);
27846
29266
  const payload = await updateTopicFromGatewayAuth(args.authContext, {
27847
29267
  id: args.topicId,
27848
- name: readString31(body.name),
27849
- description: readString31(body.description),
27850
- type: readString31(body.type),
27851
- ontologyId: readString31(body.ontologyId),
29268
+ name: readString33(body.name),
29269
+ description: readString33(body.description),
29270
+ type: readString33(body.type),
29271
+ ontologyId: readString33(body.ontologyId),
27852
29272
  clearOntologyId: readBoolean(body.clearOntologyId),
27853
- status: readString31(body.status),
27854
- visibility: readString31(body.visibility)
29273
+ status: readString33(body.status),
29274
+ visibility: readString33(body.visibility)
27855
29275
  });
27856
29276
  return successResponse(payload, {
27857
29277
  correlationId: args.correlationId,
@@ -27902,7 +29322,7 @@ async function handleTopicTree(args) {
27902
29322
  try {
27903
29323
  const payload = await getTopicTreeFromGatewayAuth(args.authContext, {
27904
29324
  id: args.topicId,
27905
- maxDepth: readNumber21(args.query.maxDepth)
29325
+ maxDepth: readNumber22(args.query.maxDepth)
27906
29326
  });
27907
29327
  return successResponse(payload, {
27908
29328
  correlationId: args.correlationId,
@@ -27922,7 +29342,7 @@ async function handleTopicCoverage(args) {
27922
29342
  const payload = await getTopicCoverageFromGatewayAuth(args.authContext, {
27923
29343
  id: args.topicId,
27924
29344
  includeDescendants: typeof args.query.includeDescendants === "boolean" ? args.query.includeDescendants : void 0,
27925
- maxDepth: readNumber21(args.query.maxDepth)
29345
+ maxDepth: readNumber22(args.query.maxDepth)
27926
29346
  });
27927
29347
  return successResponse(payload, {
27928
29348
  correlationId: args.correlationId,
@@ -27939,9 +29359,9 @@ async function handleTopicCoverage(args) {
27939
29359
  }
27940
29360
  async function handleTopicRemove(args) {
27941
29361
  try {
27942
- const body = asRecord29(args.body);
29362
+ const body = asRecord31(args.body);
27943
29363
  const payload = await removeTopicFromGatewayAuth(args.authContext, {
27944
- id: readString31(body.id) ?? readString31(body.topicId) ?? ""
29364
+ id: readString33(body.id) ?? readString33(body.topicId) ?? ""
27945
29365
  });
27946
29366
  return successResponse(payload, {
27947
29367
  correlationId: args.correlationId,
@@ -27958,22 +29378,22 @@ async function handleTopicRemove(args) {
27958
29378
  }
27959
29379
  async function handleTopicBulkCreate(args) {
27960
29380
  try {
27961
- const body = asRecord29(args.body);
27962
- const topics2 = Array.isArray(body.topics) ? body.topics.map((entry) => asRecord29(entry)).map((entry) => ({
27963
- globalId: readString31(entry.globalId) ?? "",
27964
- name: readString31(entry.name) ?? "",
27965
- description: readString31(entry.description),
27966
- type: readString31(entry.type) ?? "theme",
27967
- parentTopicId: readString31(entry.parentTopicId),
27968
- depth: readNumber21(entry.depth) ?? 0,
29381
+ const body = asRecord31(args.body);
29382
+ const topics2 = Array.isArray(body.topics) ? body.topics.map((entry) => asRecord31(entry)).map((entry) => ({
29383
+ globalId: readString33(entry.globalId) ?? "",
29384
+ name: readString33(entry.name) ?? "",
29385
+ description: readString33(entry.description),
29386
+ type: readString33(entry.type) ?? "theme",
29387
+ parentTopicId: readString33(entry.parentTopicId),
29388
+ depth: readNumber22(entry.depth) ?? 0,
27969
29389
  path: readStringArray16(entry.path) ?? [],
27970
- tenantId: readString31(entry.tenantId),
27971
- workspaceId: readString31(entry.workspaceId),
27972
- graphScopeProjectId: readString31(entry.graphScopeProjectId),
27973
- status: readString31(entry.status) ?? "active",
27974
- visibility: readString31(entry.visibility),
27975
- metadata: asRecord29(entry.metadata),
27976
- createdBy: readString31(entry.createdBy)
29390
+ tenantId: readString33(entry.tenantId),
29391
+ workspaceId: readString33(entry.workspaceId),
29392
+ graphScopeProjectId: readString33(entry.graphScopeProjectId),
29393
+ status: readString33(entry.status) ?? "active",
29394
+ visibility: readString33(entry.visibility),
29395
+ metadata: asRecord31(entry.metadata),
29396
+ createdBy: readString33(entry.createdBy)
27977
29397
  })) : [];
27978
29398
  const payload = await bulkCreateTopicsFromGatewayAuth(args.authContext, {
27979
29399
  topics: topics2
@@ -27994,10 +29414,10 @@ async function handleTopicBulkCreate(args) {
27994
29414
  }
27995
29415
 
27996
29416
  // ../../apps/gateway/src/routes/webhooks.ts
27997
- function asRecord30(value) {
29417
+ function asRecord32(value) {
27998
29418
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
27999
29419
  }
28000
- function readString32(value) {
29420
+ function readString34(value) {
28001
29421
  if (typeof value !== "string") {
28002
29422
  return void 0;
28003
29423
  }
@@ -28011,7 +29431,7 @@ function readStringArray17(value) {
28011
29431
  if (!Array.isArray(value)) {
28012
29432
  return void 0;
28013
29433
  }
28014
- const normalized = value.map((entry) => readString32(entry)).filter((entry) => Boolean(entry));
29434
+ const normalized = value.map((entry) => readString34(entry)).filter((entry) => Boolean(entry));
28015
29435
  return normalized.length > 0 ? normalized : void 0;
28016
29436
  }
28017
29437
  function handleWebhooksError(error, fallbackMessage, correlationId, policyTraceId) {
@@ -28029,16 +29449,16 @@ function handleWebhooksError(error, fallbackMessage, correlationId, policyTraceI
28029
29449
  }
28030
29450
  async function handleWebhookCreate(args) {
28031
29451
  try {
28032
- const body = asRecord30(args.body);
29452
+ const body = asRecord32(args.body);
28033
29453
  const payload = await args.authContext.convex.mutation(
28034
29454
  "events:createWebhook",
28035
29455
  {
28036
29456
  tenantId: args.authContext.tenantId,
28037
29457
  workspaceId: args.authContext.workspaceId,
28038
- topicId: readString32(body.topicId),
28039
- url: readString32(body.url) ?? "",
29458
+ topicId: readString34(body.topicId),
29459
+ url: readString34(body.url) ?? "",
28040
29460
  events: readStringArray17(body.events) ?? [],
28041
- secret: readString32(body.secret) ?? "",
29461
+ secret: readString34(body.secret) ?? "",
28042
29462
  active: readBoolean2(body.active),
28043
29463
  createdBy: args.authContext.principalId ?? args.authContext.userId
28044
29464
  }
@@ -28099,17 +29519,17 @@ async function handleWebhookGet(args) {
28099
29519
  }
28100
29520
  async function handleWebhookUpdate(args) {
28101
29521
  try {
28102
- const body = asRecord30(args.body);
29522
+ const body = asRecord32(args.body);
28103
29523
  const payload = await args.authContext.convex.mutation(
28104
29524
  "events:updateWebhook",
28105
29525
  {
28106
29526
  webhookId: args.webhookId,
28107
29527
  tenantId: args.authContext.tenantId,
28108
29528
  workspaceId: args.authContext.workspaceId,
28109
- url: readString32(body.url),
29529
+ url: readString34(body.url),
28110
29530
  events: readStringArray17(body.events),
28111
- secret: readString32(body.secret),
28112
- topicId: readString32(body.topicId),
29531
+ secret: readString34(body.secret),
29532
+ topicId: readString34(body.topicId),
28113
29533
  clearTopicId: body.topicId === null ? true : readBoolean2(body.clearTopicId),
28114
29534
  active: readBoolean2(body.active),
28115
29535
  updatedBy: args.authContext.principalId ?? args.authContext.userId
@@ -28153,12 +29573,12 @@ async function handleWebhookDelete(args) {
28153
29573
  }
28154
29574
  async function handleWebhookTest(args) {
28155
29575
  try {
28156
- const body = asRecord30(args.body);
29576
+ const body = asRecord32(args.body);
28157
29577
  const payload = await args.authContext.convex.action("events:testWebhook", {
28158
29578
  webhookId: args.webhookId,
28159
29579
  tenantId: args.authContext.tenantId,
28160
29580
  workspaceId: args.authContext.workspaceId,
28161
- topicId: readString32(body.topicId),
29581
+ topicId: readString34(body.topicId),
28162
29582
  actorId: args.authContext.principalId ?? args.authContext.userId,
28163
29583
  actorType: inferActorType({
28164
29584
  authMode: args.authContext.authMode,
@@ -28228,31 +29648,31 @@ async function handleWebhookHealth(args) {
28228
29648
  }
28229
29649
 
28230
29650
  // ../../apps/gateway/src/routes/worktrees.ts
28231
- function asRecord31(value) {
29651
+ function asRecord33(value) {
28232
29652
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
28233
29653
  }
28234
- function readString33(value) {
29654
+ function readString35(value) {
28235
29655
  if (typeof value !== "string") {
28236
29656
  return void 0;
28237
29657
  }
28238
29658
  const normalized = value.trim();
28239
29659
  return normalized.length > 0 ? normalized : void 0;
28240
29660
  }
28241
- function readNumber22(value) {
29661
+ function readNumber23(value) {
28242
29662
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
28243
29663
  }
28244
29664
  function readStringArray18(value) {
28245
29665
  if (!Array.isArray(value)) {
28246
29666
  return void 0;
28247
29667
  }
28248
- const normalized = value.map((entry) => readString33(entry)).filter((entry) => Boolean(entry));
29668
+ const normalized = value.map((entry) => readString35(entry)).filter((entry) => Boolean(entry));
28249
29669
  return normalized.length > 0 ? normalized : void 0;
28250
29670
  }
28251
29671
  function readObjectArray(value) {
28252
29672
  if (!Array.isArray(value)) {
28253
29673
  return void 0;
28254
29674
  }
28255
- const normalized = value.map((entry) => asRecord31(entry)).filter((entry) => Object.keys(entry).length > 0);
29675
+ const normalized = value.map((entry) => asRecord33(entry)).filter((entry) => Object.keys(entry).length > 0);
28256
29676
  return normalized.length > 0 ? normalized : void 0;
28257
29677
  }
28258
29678
  function readConfidenceImpact(value) {
@@ -28263,18 +29683,18 @@ function normalizeMergeOutcomes2(value) {
28263
29683
  return [];
28264
29684
  }
28265
29685
  return value.map((entry) => {
28266
- const finding = readString33(entry);
29686
+ const finding = readString35(entry);
28267
29687
  if (finding) {
28268
29688
  return finding;
28269
29689
  }
28270
- const row = asRecord31(entry);
29690
+ const row = asRecord33(entry);
28271
29691
  if (!Object.keys(row).length) {
28272
29692
  return null;
28273
29693
  }
28274
29694
  return {
28275
- beliefId: readString33(row.beliefId) ?? "",
28276
- confidence: readNumber22(row.confidence) ?? Number.NaN,
28277
- rationale: readString33(row.rationale) ?? ""
29695
+ beliefId: readString35(row.beliefId) ?? "",
29696
+ confidence: readNumber23(row.confidence) ?? Number.NaN,
29697
+ rationale: readString35(row.rationale) ?? ""
28278
29698
  };
28279
29699
  }).filter((entry) => entry !== null);
28280
29700
  }
@@ -28293,22 +29713,22 @@ function handleWorktreesError(error, fallbackMessage, correlationId, policyTrace
28293
29713
  }
28294
29714
  async function handleWorktreeCreate(args) {
28295
29715
  try {
28296
- const body = asRecord31(args.body);
29716
+ const body = asRecord33(args.body);
28297
29717
  const goCriteria = readStringArray18(body.goCriteria);
28298
29718
  const noGoSignals = readStringArray18(body.noGoSignals);
28299
29719
  const payload = await createWorktreeFromGatewayAuth(args.authContext, {
28300
- title: readString33(body.title) ?? readString33(body.name) ?? "",
28301
- topicId: readString33(body.topicId ?? body.projectId) ?? "",
28302
- topicHint: readString33(body.topicHint),
28303
- objective: readString33(body.objective),
28304
- hypothesis: readString33(body.hypothesis),
28305
- rationale: readString33(body.rationale),
28306
- worktreeType: readString33(body.worktreeType),
28307
- startDate: readNumber22(body.startDate),
28308
- endDate: readNumber22(body.endDate),
28309
- durationWeeks: readNumber22(body.durationWeeks),
29720
+ title: readString35(body.title) ?? readString35(body.name) ?? "",
29721
+ topicId: readString35(body.topicId ?? body.projectId) ?? "",
29722
+ topicHint: readString35(body.topicHint),
29723
+ objective: readString35(body.objective),
29724
+ hypothesis: readString35(body.hypothesis),
29725
+ rationale: readString35(body.rationale),
29726
+ worktreeType: readString35(body.worktreeType),
29727
+ startDate: readNumber23(body.startDate),
29728
+ endDate: readNumber23(body.endDate),
29729
+ durationWeeks: readNumber23(body.durationWeeks),
28310
29730
  confidenceImpact: readConfidenceImpact(body.confidenceImpact),
28311
- beliefFocus: readString33(body.beliefFocus),
29731
+ beliefFocus: readString35(body.beliefFocus),
28312
29732
  beliefIds: readStringArray18(body.targetBeliefIds) ?? readStringArray18(body.beliefIds) ?? readStringArray18(body.beliefs),
28313
29733
  targetBeliefIds: readStringArray18(body.targetBeliefIds),
28314
29734
  targetQuestionIds: readStringArray18(body.targetQuestionIds),
@@ -28319,23 +29739,23 @@ async function handleWorktreeCreate(args) {
28319
29739
  noGoSignals: noGoSignals ?? []
28320
29740
  } : void 0,
28321
29741
  autoShape: typeof body.autoShape === "boolean" ? body.autoShape : void 0,
28322
- domainPackId: readString33(body.domainPackId),
29742
+ domainPackId: readString35(body.domainPackId),
28323
29743
  tags: readStringArray18(body.tags),
28324
29744
  touchedPaths: readStringArray18(body.touchedPaths),
28325
- sourceRef: readString33(body.sourceRef),
28326
- sourceKind: readString33(body.sourceKind),
28327
- campaign: readNumber22(body.campaign),
28328
- lane: readString33(body.lane),
28329
- laneOrderInCampaign: readNumber22(body.laneOrderInCampaign),
28330
- orderInLane: readNumber22(body.orderInLane),
29745
+ sourceRef: readString35(body.sourceRef),
29746
+ sourceKind: readString35(body.sourceKind),
29747
+ campaign: readNumber23(body.campaign),
29748
+ lane: readString35(body.lane),
29749
+ laneOrderInCampaign: readNumber23(body.laneOrderInCampaign),
29750
+ orderInLane: readNumber23(body.orderInLane),
28331
29751
  dependsOn: readStringArray18(body.dependsOn),
28332
29752
  blocks: readStringArray18(body.blocks),
28333
- gate: readString33(body.gate),
29753
+ gate: readString35(body.gate),
28334
29754
  proofArtifacts: Array.isArray(body.proofArtifacts) ? body.proofArtifacts : void 0,
28335
- staffingHint: readString33(body.staffingHint),
28336
- lastReconciledAt: readNumber22(body.lastReconciledAt),
29755
+ staffingHint: readString35(body.staffingHint),
29756
+ lastReconciledAt: readNumber23(body.lastReconciledAt),
28337
29757
  autoFixPolicy: body.autoFixPolicy && typeof body.autoFixPolicy === "object" && !Array.isArray(body.autoFixPolicy) ? body.autoFixPolicy : void 0,
28338
- lensId: readString33(body.lensId)
29758
+ lensId: readString35(body.lensId)
28339
29759
  });
28340
29760
  return successResponse(payload, {
28341
29761
  status: 201,
@@ -28354,12 +29774,12 @@ async function handleWorktreeCreate(args) {
28354
29774
  async function handleWorktreeList(args) {
28355
29775
  try {
28356
29776
  const payload = await listWorktreesFromGatewayAuth(args.authContext, {
28357
- topicId: readString33(args.query.topicId) ?? "",
28358
- status: readString33(args.query.status),
28359
- groupBy: readString33(args.query.groupBy),
28360
- lane: readString33(args.query.lane),
28361
- campaign: readNumber22(args.query.campaign),
28362
- limit: readNumber22(args.query.limit)
29777
+ topicId: readString35(args.query.topicId) ?? "",
29778
+ status: readString35(args.query.status),
29779
+ groupBy: readString35(args.query.groupBy),
29780
+ lane: readString35(args.query.lane),
29781
+ campaign: readNumber23(args.query.campaign),
29782
+ limit: readNumber23(args.query.limit)
28363
29783
  });
28364
29784
  return successResponse(payload, {
28365
29785
  correlationId: args.correlationId,
@@ -28377,11 +29797,11 @@ async function handleWorktreeList(args) {
28377
29797
  async function handleWorktreeListAll(args) {
28378
29798
  try {
28379
29799
  const payload = await listAllWorktreesFromGatewayAuth(args.authContext, {
28380
- status: readString33(args.query.status),
28381
- lane: readString33(args.query.lane),
28382
- campaign: readNumber22(args.query.campaign),
28383
- groupBy: readString33(args.query.groupBy),
28384
- limit: readNumber22(args.query.limit)
29800
+ status: readString35(args.query.status),
29801
+ lane: readString35(args.query.lane),
29802
+ campaign: readNumber23(args.query.campaign),
29803
+ groupBy: readString35(args.query.groupBy),
29804
+ limit: readNumber23(args.query.limit)
28385
29805
  });
28386
29806
  return successResponse(payload, {
28387
29807
  correlationId: args.correlationId,
@@ -28399,9 +29819,9 @@ async function handleWorktreeListAll(args) {
28399
29819
  async function handleWorktreeListCampaigns(args) {
28400
29820
  try {
28401
29821
  const payload = await listCampaignsFromGatewayAuth(args.authContext, {
28402
- topicId: readString33(args.query.topicId),
28403
- status: readString33(args.query.status),
28404
- limit: readNumber22(args.query.limit)
29822
+ topicId: readString35(args.query.topicId),
29823
+ status: readString35(args.query.status),
29824
+ limit: readNumber23(args.query.limit)
28405
29825
  });
28406
29826
  return successResponse(payload, {
28407
29827
  correlationId: args.correlationId,
@@ -28436,27 +29856,27 @@ async function handleWorktreeActivate(args) {
28436
29856
  }
28437
29857
  async function handleWorktreeUpdate(args) {
28438
29858
  try {
28439
- const body = asRecord31(args.body);
29859
+ const body = asRecord33(args.body);
28440
29860
  const payload = await updateWorktreeFromGatewayAuth(args.authContext, {
28441
29861
  id: args.worktreeId,
28442
- objective: readString33(body.objective),
28443
- hypothesis: readString33(body.hypothesis),
28444
- rationale: readString33(body.rationale),
28445
- campaign: readNumber22(body.campaign),
28446
- lane: readString33(body.lane),
28447
- laneOrderInCampaign: readNumber22(body.laneOrderInCampaign),
28448
- orderInLane: readNumber22(body.orderInLane),
29862
+ objective: readString35(body.objective),
29863
+ hypothesis: readString35(body.hypothesis),
29864
+ rationale: readString35(body.rationale),
29865
+ campaign: readNumber23(body.campaign),
29866
+ lane: readString35(body.lane),
29867
+ laneOrderInCampaign: readNumber23(body.laneOrderInCampaign),
29868
+ orderInLane: readNumber23(body.orderInLane),
28449
29869
  dependsOn: readStringArray18(body.dependsOn),
28450
29870
  blocks: readStringArray18(body.blocks),
28451
- gate: readString33(body.gate),
28452
- status: readString33(body.status),
28453
- topicId: readString33(body.topicId),
29871
+ gate: readString35(body.gate),
29872
+ status: readString35(body.status),
29873
+ topicId: readString35(body.topicId),
28454
29874
  additionalTopicIds: readStringArray18(body.additionalTopicIds),
28455
29875
  proofArtifacts: Array.isArray(body.proofArtifacts) ? body.proofArtifacts : void 0,
28456
- staffingHint: readString33(body.staffingHint),
28457
- lastReconciledAt: readNumber22(body.lastReconciledAt),
29876
+ staffingHint: readString35(body.staffingHint),
29877
+ lastReconciledAt: readNumber23(body.lastReconciledAt),
28458
29878
  autoFixPolicy: body.autoFixPolicy && typeof body.autoFixPolicy === "object" ? body.autoFixPolicy : void 0,
28459
- lensId: readString33(body.lensId)
29879
+ lensId: readString35(body.lensId)
28460
29880
  });
28461
29881
  return successResponse(payload, {
28462
29882
  correlationId: args.correlationId,
@@ -28473,11 +29893,11 @@ async function handleWorktreeUpdate(args) {
28473
29893
  }
28474
29894
  async function handleWorktreeMerge(args) {
28475
29895
  try {
28476
- const body = asRecord31(args.body);
29896
+ const body = asRecord33(args.body);
28477
29897
  const outcomes = normalizeMergeOutcomes2(body.outcomes);
28478
29898
  const payload = await mergeWorktreeFromGatewayAuth(args.authContext, {
28479
29899
  id: args.worktreeId,
28480
- summary: readString33(body.summary),
29900
+ summary: readString35(body.summary),
28481
29901
  outcomes
28482
29902
  });
28483
29903
  return successResponse(payload, {
@@ -28495,7 +29915,7 @@ async function handleWorktreeMerge(args) {
28495
29915
  }
28496
29916
  async function handleWorktreeUpdateTargets(args) {
28497
29917
  try {
28498
- const body = asRecord31(args.body);
29918
+ const body = asRecord33(args.body);
28499
29919
  const payload = await updateWorktreeTargetsFromGatewayAuth(
28500
29920
  args.authContext,
28501
29921
  {
@@ -28521,11 +29941,11 @@ async function handleWorktreeUpdateTargets(args) {
28521
29941
  }
28522
29942
  async function handleWorktreeComplete(args) {
28523
29943
  try {
28524
- const body = asRecord31(args.body);
29944
+ const body = asRecord33(args.body);
28525
29945
  const payload = await completeWorktreeRecordFromGatewayAuth(
28526
29946
  args.authContext,
28527
29947
  {
28528
- worktreeId: readString33(body.worktreeId) ?? "",
29948
+ worktreeId: readString35(body.worktreeId) ?? "",
28529
29949
  keyFindings: readStringArray18(body.keyFindings),
28530
29950
  decisionsReached: readStringArray18(body.decisionsReached),
28531
29951
  nextSteps: readStringArray18(body.nextSteps)
@@ -28546,9 +29966,9 @@ async function handleWorktreeComplete(args) {
28546
29966
  }
28547
29967
  async function handleWorktreeAdvancePhase(args) {
28548
29968
  try {
28549
- const body = asRecord31(args.body);
29969
+ const body = asRecord33(args.body);
28550
29970
  const payload = await advanceWorktreePhaseFromGatewayAuth(args.authContext, {
28551
- worktreeId: readString33(body.worktreeId) ?? ""
29971
+ worktreeId: readString35(body.worktreeId) ?? ""
28552
29972
  });
28553
29973
  return successResponse(payload, {
28554
29974
  correlationId: args.correlationId,
@@ -28565,10 +29985,10 @@ async function handleWorktreeAdvancePhase(args) {
28565
29985
  }
28566
29986
  async function handleWorktreeSetPhase(args) {
28567
29987
  try {
28568
- const body = asRecord31(args.body);
29988
+ const body = asRecord33(args.body);
28569
29989
  const payload = await setWorktreePhaseFromGatewayAuth(args.authContext, {
28570
- worktreeId: readString33(body.worktreeId) ?? "",
28571
- phase: readString33(body.phase) ?? ""
29990
+ worktreeId: readString35(body.worktreeId) ?? "",
29991
+ phase: readString35(body.phase) ?? ""
28572
29992
  });
28573
29993
  return successResponse(payload, {
28574
29994
  correlationId: args.correlationId,
@@ -28585,12 +30005,12 @@ async function handleWorktreeSetPhase(args) {
28585
30005
  }
28586
30006
  async function handleWorktreePatchState(args) {
28587
30007
  try {
28588
- const body = asRecord31(args.body);
30008
+ const body = asRecord33(args.body);
28589
30009
  const payload = await patchWorktreeStateFromGatewayAuth(
28590
30010
  args.authContext,
28591
30011
  {
28592
- worktreeId: readString33(body.worktreeId) ?? "",
28593
- patch: asRecord31(body.patch)
30012
+ worktreeId: readString35(body.worktreeId) ?? "",
30013
+ patch: asRecord33(body.patch)
28594
30014
  }
28595
30015
  );
28596
30016
  return successResponse(payload, {
@@ -28608,7 +30028,7 @@ async function handleWorktreePatchState(args) {
28608
30028
  }
28609
30029
  async function handleWorktreeBulkCreate(args) {
28610
30030
  try {
28611
- const body = asRecord31(args.body);
30031
+ const body = asRecord33(args.body);
28612
30032
  const payload = await bulkCreateWorktreesFromGatewayAuth(args.authContext, {
28613
30033
  worktrees: Array.isArray(body.worktrees) ? body.worktrees : []
28614
30034
  });
@@ -28627,6 +30047,6 @@ async function handleWorktreeBulkCreate(args) {
28627
30047
  }
28628
30048
  }
28629
30049
 
28630
- export { handleBeliefArchive, handleBeliefBatchUpdateCriticality, handleBeliefBisect, handleBeliefConfidenceHistory, handleBeliefCreate, handleBeliefCreateContract, handleBeliefFork, handleBeliefGet, handleBeliefLineage, handleBeliefLink, handleBeliefList, handleBeliefReassignTopic, handleBeliefRefine, handleBeliefRelationships, handleBeliefUnlinkEvidence, handleBeliefUpdateConfidence, handleBeliefUpdateCriticality, handleBeliefUpdateRationale, handleBeliefUpdateStatus, handleContradictionFlag, handleContradictionGet, handleContradictionList, handleEdgeBatchCreate, handleEdgeCreate, handleEdgeDelete, handleEdgeList, handleEdgeRemove, handleEdgeTraverse, handleEdgeUpdate, handleEdgesRemoveBetween, handleEventsList, handleEventsReplay, handleEvidenceClassify, handleEvidenceClassifyBatch, handleEvidenceCreate, handleEvidenceFlagIncorrect, handleEvidenceGet, handleEvidenceLink, handleEvidenceList, handleEvidenceRemove, handleEvidenceSearch, handleEvidenceUpdate, handleEvidenceUpdateStatus, handleEvidenceUpdateVerificationStatus, handleGraphAnalysisCompute, handleGraphAnalysisLatest, handleGraphAnalysisList, handleGraphAnalysisListChanges, handleGraphAnalysisListSuggestions, handleGraphAnalysisSave, handleGraphAnalysisSaveSuggestions, handleGraphAnalysisUpdateSuggestion, handleGraphAnalyze, handleGraphBias, handleGraphEdgeList, handleGraphFalsify, handleGraphGaps, handleGraphNeighborhood, handleGraphNodeList, handleGraphRecommendationGet, handleGraphRecommendationStatus, handleGraphRecommendationsList, handleGraphTraverse, handleIdentityWhoami, handleOntologyBind, handleOntologyGet, handleOntologyList, handleOntologyMatch, handleOrgGraphByProvenance, handleOrgGraphNodeGet, handleOrgGraphPublished, handleOrgGraphSearch, handleQuestionAdd, handleQuestionAdvanceToConviction, handleQuestionAnswer, handleQuestionArchive, handleQuestionBatchCreate, handleQuestionCreate, handleQuestionDelete, handleQuestionFinalizeConviction, handleQuestionGet, handleQuestionGetAnswer, handleQuestionList, handleQuestionRefine, handleQuestionUpdate, handleQuestionUpdateConviction, handleQuestionUpdatePriority, handleQuestionUpdateStatus, handleSearchResources, handleSourceGet, handleSourceUpsert, handleTaskComplete, handleTaskCreate, handleTaskList, handleTaskUpdate, handleTopicBulkCreate, handleTopicCoverage, handleTopicCreate, handleTopicGet, handleTopicList, handleTopicRemove, handleTopicTree, handleTopicUpdate, handleWebhookCreate, handleWebhookDelete, handleWebhookDeliveries, handleWebhookGet, handleWebhookHealth, handleWebhookList, handleWebhookTest, handleWebhookUpdate, handleWorktreeActivate, handleWorktreeAdvancePhase, handleWorktreeBulkCreate, handleWorktreeComplete, handleWorktreeCreate, handleWorktreeList, handleWorktreeListAll, handleWorktreeListCampaigns, handleWorktreeMerge, handleWorktreePatchState, handleWorktreeSetPhase, handleWorktreeUpdate, handleWorktreeUpdateTargets };
30050
+ export { __testOnly, extractPermitWebhookTenantKeys, handleBeliefArchive, handleBeliefBatchUpdateCriticality, handleBeliefBisect, handleBeliefConfidenceHistory, handleBeliefCreate, handleBeliefCreateContract, handleBeliefFork, handleBeliefGet, handleBeliefLineage, handleBeliefLink, handleBeliefList, handleBeliefReassignTopic, handleBeliefRefine, handleBeliefRelationships, handleBeliefUnlinkEvidence, handleBeliefUpdateConfidence, handleBeliefUpdateCriticality, handleBeliefUpdateRationale, handleBeliefUpdateStatus, handleClerkWebhook, handleContradictionFlag, handleContradictionGet, handleContradictionList, handleEdgeBatchCreate, handleEdgeCreate, handleEdgeDelete, handleEdgeList, handleEdgeRemove, handleEdgeTraverse, handleEdgeUpdate, handleEdgesRemoveBetween, handleEventsList, handleEventsReplay, handleEvidenceClassify, handleEvidenceClassifyBatch, handleEvidenceCreate, handleEvidenceFlagIncorrect, handleEvidenceGet, handleEvidenceLink, handleEvidenceList, handleEvidenceRemove, handleEvidenceSearch, handleEvidenceUpdate, handleEvidenceUpdateStatus, handleEvidenceUpdateVerificationStatus, handleGraphAnalysisCompute, handleGraphAnalysisLatest, handleGraphAnalysisList, handleGraphAnalysisListChanges, handleGraphAnalysisListSuggestions, handleGraphAnalysisSave, handleGraphAnalysisSaveSuggestions, handleGraphAnalysisUpdateSuggestion, handleGraphAnalyze, handleGraphBias, handleGraphEdgeList, handleGraphFalsify, handleGraphGaps, handleGraphNeighborhood, handleGraphNodeList, handleGraphRecommendationGet, handleGraphRecommendationStatus, handleGraphRecommendationsList, handleGraphTraverse, handleIdentityWhoami, handleOntologyBind, handleOntologyGet, handleOntologyList, handleOntologyMatch, handleOrgGraphByProvenance, handleOrgGraphNodeGet, handleOrgGraphPublished, handleOrgGraphSearch, handlePermitProjectionWebhook, handleQuestionAdd, handleQuestionAdvanceToConviction, handleQuestionAnswer, handleQuestionArchive, handleQuestionBatchCreate, handleQuestionCreate, handleQuestionDelete, handleQuestionFinalizeConviction, handleQuestionGet, handleQuestionGetAnswer, handleQuestionList, handleQuestionRefine, handleQuestionUpdate, handleQuestionUpdateConviction, handleQuestionUpdatePriority, handleQuestionUpdateStatus, handleSearchResources, handleSourceGet, handleSourceUpsert, handleTaskComplete, handleTaskCreate, handleTaskList, handleTaskUpdate, handleTopicBulkCreate, handleTopicCoverage, handleTopicCreate, handleTopicGet, handleTopicList, handleTopicRemove, handleTopicTree, handleTopicUpdate, handleWebhookCreate, handleWebhookDelete, handleWebhookDeliveries, handleWebhookGet, handleWebhookHealth, handleWebhookList, handleWebhookTest, handleWebhookUpdate, handleWorktreeActivate, handleWorktreeAdvancePhase, handleWorktreeBulkCreate, handleWorktreeComplete, handleWorktreeCreate, handleWorktreeList, handleWorktreeListAll, handleWorktreeListCampaigns, handleWorktreeMerge, handleWorktreePatchState, handleWorktreeSetPhase, handleWorktreeUpdate, handleWorktreeUpdateTargets, hasPermitWebhookTenantScope, isPermitWebhookAuthorized };
28631
30051
  //# sourceMappingURL=gateway.js.map
28632
30052
  //# sourceMappingURL=gateway.js.map