@lucern/mcp 0.3.0-alpha.15 → 0.3.0-alpha.17

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
@@ -782,6 +782,7 @@ defineTable({
782
782
  shape: z.object({
783
783
  "tenantId": idOf("tenants"),
784
784
  "workspaceId": idOf("workspaces").optional(),
785
+ "environment": z.enum(["dev", "staging", "prod"]).optional(),
785
786
  "keyPrefix": z.enum(["luc", "stk"]),
786
787
  "keyHash": z.string(),
787
788
  "keyHint": z.string(),
@@ -809,7 +810,7 @@ defineTable({
809
810
  shape: z.object({
810
811
  "tenantId": idOf("tenants").optional(),
811
812
  "apiKeyId": idOf("apiKeys").optional(),
812
- "action": z.enum(["key_created", "key_revoked", "key_expired", "key_used", "tenant_secret_created", "tenant_secret_rotated", "tenant_secret_revoked", "tenant_slot_binding_upserted", "tenant_slot_binding_revoked", "proxy_token_minted", "proxy_token_lease_issued", "proxy_token_lease_renewed", "proxy_token_lease_revoked", "proxy_request_recorded", "tenant_created", "tenant_updated", "tenant_suspended", "tenant_archived", "tenant_reactivated", "principal_created", "principal_updated", "principal_suspended", "principal_identity_alias_upserted", "principal_identity_alias_revoked", "membership_created", "membership_updated", "membership_revoked", "group_created", "group_updated", "group_deleted", "group_member_added", "group_member_removed", "workspace_created", "workspace_updated", "workspace_archived", "workspace_deployment_set", "workspace_deployment_removed", "deployment_host_registered", "deployment_host_revoked", "service_key_created", "service_key_rotated", "service_key_revoked", "service_key_used", "service_key_auth_failed", "session_created", "session_validated", "session_revoked", "session_cascade_revoked", "session_expired", "sandbox_created", "sandbox_secret_injected", "sandbox_execution_started", "sandbox_execution_completed", "sandbox_limit_violated", "policy_created", "policy_updated", "policy_enforced", "policy_archived", "permit_sync_enqueued", "permit_sync_succeeded", "permit_sync_failed", "permit_sync_skipped", "agent_registered", "agent_updated", "tool_registered", "tool_updated", "pack_entitled", "pack_installed", "pack_enabled", "pack_disabled", "pack_entitlement_revoked", "pack_upgraded", "pack_upgrade_committed", "pack_upgrade_rolled_back", "pack_group_assigned", "pack_group_unassigned", "methodology_pack_created", "methodology_pack_updated", "methodology_pack_assigned", "methodology_pack_removed", "pack_assigned_to_group", "pack_revoked_from_group", "pack_ontology_materialized", "pack_ontology_topic_bound", "cutover_flag_set", "cutover_flag_cleared"]),
813
+ "action": z.enum(["key_created", "key_revoked", "key_expired", "key_used", "tenant_secret_created", "tenant_secret_rotated", "tenant_secret_revoked", "tenant_slot_binding_upserted", "tenant_slot_binding_revoked", "proxy_token_minted", "proxy_token_lease_issued", "proxy_token_lease_renewed", "proxy_token_lease_revoked", "proxy_request_recorded", "tenant_created", "tenant_updated", "tenant_suspended", "tenant_archived", "tenant_reactivated", "tenant_clerk_organization_linked", "principal_created", "principal_updated", "principal_suspended", "principal_identity_alias_upserted", "principal_identity_alias_revoked", "membership_created", "membership_updated", "membership_revoked", "group_created", "group_updated", "group_deleted", "group_member_added", "group_member_removed", "workspace_created", "workspace_updated", "workspace_archived", "workspace_deployment_set", "workspace_deployment_removed", "deployment_host_registered", "deployment_host_revoked", "service_key_created", "service_key_rotated", "service_key_revoked", "service_key_used", "service_key_auth_failed", "session_created", "session_validated", "session_revoked", "session_cascade_revoked", "session_expired", "sandbox_created", "sandbox_secret_injected", "sandbox_execution_started", "sandbox_execution_completed", "sandbox_limit_violated", "policy_created", "policy_updated", "policy_enforced", "policy_archived", "permit_sync_enqueued", "permit_sync_succeeded", "permit_sync_failed", "permit_sync_skipped", "agent_registered", "agent_updated", "tool_registered", "tool_updated", "pack_entitled", "pack_installed", "pack_enabled", "pack_disabled", "pack_entitlement_revoked", "pack_upgraded", "pack_upgrade_committed", "pack_upgrade_rolled_back", "pack_group_assigned", "pack_group_unassigned", "methodology_pack_created", "methodology_pack_updated", "methodology_pack_assigned", "methodology_pack_removed", "pack_assigned_to_group", "pack_revoked_from_group", "pack_ontology_materialized", "pack_ontology_topic_bound", "cutover_flag_set", "cutover_flag_cleared"]),
813
814
  "actorClerkId": z.string(),
814
815
  "details": z.any().optional(),
815
816
  "createdAt": z.number()
@@ -6938,7 +6939,7 @@ function compactRecord2(input) {
6938
6939
  Object.entries(input).filter(([, value]) => value !== void 0)
6939
6940
  );
6940
6941
  }
6941
- var listBeliefsProjection = defineProjection({
6942
+ defineProjection({
6942
6943
  contractName: "list_beliefs",
6943
6944
  inputSchema: listBeliefsInputSchema,
6944
6945
  project: (input) => compactRecord2({
@@ -9447,7 +9448,7 @@ var IDENTITY_WHOAMI = {
9447
9448
  response: {
9448
9449
  description: "Canonical identity summary for the current session",
9449
9450
  fields: {
9450
- principalId: "string \u2014 canonical federated principal identifier",
9451
+ principalId: "string \u2014 canonical principal identifier; for humans this is the Clerk user_... ID",
9451
9452
  principalType: "string \u2014 human, service, agent, group, or external_viewer",
9452
9453
  tenantId: "string | undefined \u2014 resolved tenant scope",
9453
9454
  workspaceId: "string | undefined \u2014 resolved workspace scope",
@@ -9461,7 +9462,7 @@ var IDENTITY_WHOAMI = {
9461
9462
  };
9462
9463
  var RESOLVE_INTERACTIVE_PRINCIPAL = {
9463
9464
  name: "resolve_interactive_principal",
9464
- 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.",
9465
+ 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 Clerk subject into tenant/workspace authorization context.",
9465
9466
  parameters: {
9466
9467
  clerkId: {
9467
9468
  type: "string",
@@ -9484,7 +9485,7 @@ var RESOLVE_INTERACTIVE_PRINCIPAL = {
9484
9485
  response: {
9485
9486
  description: "Permit-backed Lucern principal context for tenant SDK bootstrap",
9486
9487
  fields: {
9487
- principalId: "string \u2014 canonical Lucern principal identifier",
9488
+ principalId: "string \u2014 canonical Clerk user_... ID for human sessions",
9488
9489
  principalType: "string \u2014 human, service, agent, group, or external_viewer",
9489
9490
  clerkId: "string \u2014 authenticated Clerk subject alias",
9490
9491
  tenantId: "string \u2014 resolved tenant scope",
@@ -10312,7 +10313,7 @@ var MANAGE_WRITE_POLICY = {
10312
10313
  },
10313
10314
  role: {
10314
10315
  type: "string",
10315
- description: "Role to set policy for (required for 'set'). E.g. 'agent:internal', 'user:analyst'."
10316
+ description: "Role to set policy for (required for 'set'). E.g. 'agent:internal' or a Permit role key such as 'workspace_admin'."
10316
10317
  },
10317
10318
  permission: {
10318
10319
  type: "string",
@@ -12242,11 +12243,8 @@ var identityContracts = [
12242
12243
  sdkNamespace: "identity",
12243
12244
  sdkMethod: "whoami",
12244
12245
  summary: "Describe the current gateway principal.",
12245
- convex: {
12246
- module: "identity",
12247
- functionName: "whoami",
12248
- kind: "query",
12249
- inputProjection: withPrincipal
12246
+ gateway: {
12247
+ handler: "identity.whoami"
12250
12248
  }
12251
12249
  }),
12252
12250
  surfaceContract({
@@ -12266,7 +12264,7 @@ var identityContracts = [
12266
12264
  providerProjectId: z.string().min(1).optional()
12267
12265
  }),
12268
12266
  convex: {
12269
- module: "identity",
12267
+ module: "platform",
12270
12268
  functionName: "resolveInteractivePrincipal",
12271
12269
  kind: "query"
12272
12270
  }
@@ -12350,15 +12348,6 @@ var beliefLookupInput = (input) => compactRecord4({
12350
12348
  var beliefNodeInput = (input) => compactRecord4({
12351
12349
  nodeId: input.nodeId ?? input.id ?? input.beliefId
12352
12350
  });
12353
- var beliefTopicInput = (input) => {
12354
- const parsed = listBeliefsProjection.inputSchema.safeParse(input);
12355
- if (!parsed.success) {
12356
- throw new Error(
12357
- `list_beliefs projection input rejected: ${parsed.error.message}`
12358
- );
12359
- }
12360
- return compactRecord4(listBeliefsProjection.project(parsed.data));
12361
- };
12362
12351
  var createBeliefInput = (input, context) => {
12363
12352
  return withUserId(
12364
12353
  compactRecord4({
@@ -12447,11 +12436,8 @@ var beliefsContracts = [
12447
12436
  sdkNamespace: "beliefs",
12448
12437
  sdkMethod: "listBeliefs",
12449
12438
  summary: "List beliefs for a topic.",
12450
- convex: {
12451
- module: "beliefs",
12452
- functionName: "getByTopic",
12453
- kind: "query",
12454
- inputProjection: beliefTopicInput
12439
+ gateway: {
12440
+ handler: "beliefs.list"
12455
12441
  },
12456
12442
  args: listBeliefsInputSchema
12457
12443
  }),
@@ -12636,12 +12622,6 @@ var evidenceIdInput = (input) => compactRecord4({
12636
12622
  insightId: input.insightId,
12637
12623
  nodeId: input.nodeId ?? input.id ?? input.evidenceId
12638
12624
  });
12639
- var evidenceTopicInput = (input) => compactRecord4({
12640
- topicId: input.topicId,
12641
- status: input.status,
12642
- userId: input.userId,
12643
- limit: input.limit
12644
- });
12645
12625
  var createEvidenceInput = (input, context) => {
12646
12626
  const parsed = createEvidenceProjection.inputSchema.safeParse(input);
12647
12627
  if (!parsed.success) {
@@ -12772,11 +12752,8 @@ var evidenceContracts = [
12772
12752
  sdkNamespace: "evidence",
12773
12753
  sdkMethod: "listEvidence",
12774
12754
  summary: "List evidence for a topic.",
12775
- convex: {
12776
- module: "evidence",
12777
- functionName: "getByTopic",
12778
- kind: "query",
12779
- inputProjection: evidenceTopicInput
12755
+ gateway: {
12756
+ handler: "evidence.list"
12780
12757
  }
12781
12758
  }),
12782
12759
  surfaceContract({
@@ -13011,11 +12988,8 @@ var questionsContracts = [
13011
12988
  sdkNamespace: "questions",
13012
12989
  sdkMethod: "listQuestions",
13013
12990
  summary: "List questions for a topic.",
13014
- convex: {
13015
- module: "questions",
13016
- functionName: "getByTopic",
13017
- kind: "query",
13018
- inputProjection: questionTopicInput
12991
+ gateway: {
12992
+ handler: "questions.list"
13019
12993
  }
13020
12994
  }),
13021
12995
  surfaceContract({
@@ -14120,6 +14094,19 @@ var worktreeEvidenceSignalInputSchema = z.object({
14120
14094
  progress: z.string().optional().describe("Collection progress note for the signal."),
14121
14095
  notes: z.string().optional().describe("Additional evidence collection notes.")
14122
14096
  }).passthrough().describe("Evidence signal embedded in the worktree plan.");
14097
+ var worktreeDocCompanionTargetSchema = z.object({
14098
+ docPath: z.string().describe(
14099
+ "Repo-relative path to a documentation file the worktree promises to update."
14100
+ ),
14101
+ sectionAnchor: z.string().optional().describe(
14102
+ "Markdown heading anchor (e.g. '## Function-surface manifest') that scopes the promised update."
14103
+ ),
14104
+ reason: z.string().describe(
14105
+ "Why this doc section must be updated for the worktree to be complete."
14106
+ )
14107
+ }).passthrough().describe(
14108
+ "Intent-driven docs companion target. pr-gate-reviewer verifies that the PR actually touches each declared (docPath, sectionAnchor). Distinct from the touch-driven docs-loop. See docs/development/docs-sync-discipline.md Lock 3."
14109
+ );
14123
14110
  var worktreeDecisionGateInputSchema = z.object({
14124
14111
  goCriteria: z.array(z.string()).describe("Criteria that must hold for the worktree to proceed."),
14125
14112
  noGoSignals: z.array(z.string()).describe("Signals that stop or redirect the worktree."),
@@ -14152,6 +14139,9 @@ var addWorktreeArgs = z.object({
14152
14139
  keyQuestions: z.array(worktreeKeyQuestionInputSchema).optional().describe("Inline key questions captured as part of the worktree plan."),
14153
14140
  evidenceSignals: z.array(worktreeEvidenceSignalInputSchema).optional().describe("Evidence signals the worktree needs to collect or validate."),
14154
14141
  decisionGate: worktreeDecisionGateInputSchema.optional(),
14142
+ docCompanionTargets: z.array(worktreeDocCompanionTargetSchema).optional().describe(
14143
+ "Doc sections the worktree promises to update at PR time. Enforced by pr-gate-reviewer (Lock 3)."
14144
+ ),
14155
14145
  goCriteria: z.array(z.string()).optional().describe("Shorthand go criteria used to build decisionGate."),
14156
14146
  noGoSignals: z.array(z.string()).optional().describe("Shorthand no-go signals used to build decisionGate."),
14157
14147
  proofArtifacts: z.array(z.unknown()).optional().describe("Expected proof artifacts required to close the worktree."),
@@ -18486,7 +18476,7 @@ async function resolveBeliefTopicId(ctx, beliefId) {
18486
18476
  if (!normalizedBeliefId) {
18487
18477
  return void 0;
18488
18478
  }
18489
- return fetchRecordTopicId(ctx, api.epistemicBeliefs.getById, {
18479
+ return fetchRecordTopicId(ctx, api.beliefs.getById, {
18490
18480
  beliefId: normalizedBeliefId,
18491
18481
  nodeId: normalizedBeliefId
18492
18482
  });
@@ -18496,7 +18486,7 @@ async function resolveQuestionTopicId(ctx, questionId) {
18496
18486
  if (!normalizedQuestionId) {
18497
18487
  return void 0;
18498
18488
  }
18499
- return fetchRecordTopicId(ctx, api.epistemicQuestions.getById, {
18489
+ return fetchRecordTopicId(ctx, api.questions.getById, {
18500
18490
  questionId: normalizedQuestionId,
18501
18491
  nodeId: normalizedQuestionId
18502
18492
  });
@@ -18901,7 +18891,7 @@ function readStringArray3(value) {
18901
18891
  async function resolveBeliefTopicIdWithGatewayAuth(authContext, beliefId) {
18902
18892
  const normalizedBeliefId = resolveExternalId(beliefId) ?? beliefId;
18903
18893
  const belief = await authContext.convex.query(
18904
- api.epistemicBeliefs.getById,
18894
+ api.beliefs.getById,
18905
18895
  {
18906
18896
  beliefId: normalizedBeliefId,
18907
18897
  nodeId: normalizedBeliefId
@@ -18931,13 +18921,13 @@ async function emitBeliefEventFromGatewayAuth(authContext, args) {
18931
18921
  function createGatewayBeliefPort(authContext) {
18932
18922
  return {
18933
18923
  fetchBelief(rawId) {
18934
- return authContext.convex.query(api.epistemicBeliefs.getById, {
18924
+ return authContext.convex.query(api.beliefs.getById, {
18935
18925
  beliefId: rawId,
18936
18926
  nodeId: rawId
18937
18927
  });
18938
18928
  },
18939
18929
  listBeliefsByTopic(args) {
18940
- return authContext.convex.query(api.epistemicBeliefs.getByTopic, {
18930
+ return authContext.convex.query(api.beliefs.getByTopic, {
18941
18931
  topicId: args.topicId,
18942
18932
  userId: authContext.userId,
18943
18933
  status: args.status,
@@ -18948,7 +18938,7 @@ function createGatewayBeliefPort(authContext) {
18948
18938
  });
18949
18939
  },
18950
18940
  createBelief(input) {
18951
- return authContext.convex.mutation(api.epistemicBeliefs.create, {
18941
+ return authContext.convex.mutation(api.beliefs.create, {
18952
18942
  topicId: input.topicId,
18953
18943
  formulation: input.text,
18954
18944
  rationale: input.rationale,
@@ -18965,7 +18955,7 @@ function createGatewayBeliefPort(authContext) {
18965
18955
  });
18966
18956
  },
18967
18957
  refineBelief(input) {
18968
- return authContext.convex.mutation(api.epistemicBeliefs.refineBelief, {
18958
+ return authContext.convex.mutation(api.beliefs.refineBelief, {
18969
18959
  nodeId: input.beliefRawId,
18970
18960
  canonicalText: input.text,
18971
18961
  rationale: input.rationale,
@@ -18973,7 +18963,7 @@ function createGatewayBeliefPort(authContext) {
18973
18963
  });
18974
18964
  },
18975
18965
  forkBelief(input) {
18976
- return authContext.convex.mutation(api.epistemicBeliefs.forkBelief, {
18966
+ return authContext.convex.mutation(api.beliefs.forkBelief, {
18977
18967
  parentNodeId: input.beliefRawId,
18978
18968
  newFormulation: input.text,
18979
18969
  forkReason: input.forkReason,
@@ -18982,7 +18972,7 @@ function createGatewayBeliefPort(authContext) {
18982
18972
  });
18983
18973
  },
18984
18974
  modulateConfidence(input) {
18985
- return authContext.convex.mutation(api.epistemicBeliefs.modulateConfidence, {
18975
+ return authContext.convex.mutation(api.beliefs.modulateConfidence, {
18986
18976
  nodeId: input.beliefRawId,
18987
18977
  trigger: input.trigger,
18988
18978
  rationale: input.rationale,
@@ -18999,25 +18989,25 @@ function createGatewayBeliefPort(authContext) {
18999
18989
  });
19000
18990
  },
19001
18991
  archiveBelief(input) {
19002
- return authContext.convex.mutation(api.epistemicBeliefs.archive, {
18992
+ return authContext.convex.mutation(api.beliefs.archive, {
19003
18993
  nodeId: input.beliefRawId,
19004
18994
  reason: input.reason,
19005
18995
  userId: authContext.userId
19006
18996
  });
19007
18997
  },
19008
18998
  getLineage(rawId) {
19009
- return authContext.convex.query(api.epistemicBeliefs.getLineage, {
18999
+ return authContext.convex.query(api.beliefs.getLineage, {
19010
19000
  nodeId: rawId
19011
19001
  });
19012
19002
  },
19013
19003
  getConfidenceHistory(rawId) {
19014
- return authContext.convex.query(api.epistemicBeliefs.getConfidenceHistory, {
19004
+ return authContext.convex.query(api.beliefs.getConfidenceHistory, {
19015
19005
  nodeId: rawId
19016
19006
  });
19017
19007
  },
19018
19008
  createContract(args) {
19019
19009
  return authContext.convex.mutation(
19020
- api.epistemicContracts.createEpistemicContract,
19010
+ api.contracts.createEpistemicContract,
19021
19011
  {
19022
19012
  beliefNodeId: args.beliefRawId,
19023
19013
  title: args.input.title,
@@ -19036,7 +19026,7 @@ function createGatewayBeliefPort(authContext) {
19036
19026
  );
19037
19027
  },
19038
19028
  getRelationships(rawId) {
19039
- return authContext.convex.query(api.epistemicBeliefs.getRelationships, {
19029
+ return authContext.convex.query(api.beliefs.getRelationships, {
19040
19030
  nodeId: rawId,
19041
19031
  direction: "both"
19042
19032
  });
@@ -19184,7 +19174,7 @@ async function getBeliefRelationshipsFromGatewayAuth(authContext, id, direction)
19184
19174
  }
19185
19175
  function updateBeliefStatusFromGatewayAuth(authContext, input) {
19186
19176
  const externalNodeId = input.id ?? input.nodeId ?? input.beliefId;
19187
- return authContext.convex.mutation(api.epistemicBeliefs.updateStatus, {
19177
+ return authContext.convex.mutation(api.beliefs.updateStatus, {
19188
19178
  nodeId: resolveBeliefNodeId(input),
19189
19179
  status: input.status,
19190
19180
  reason: input.reason,
@@ -19196,7 +19186,7 @@ function updateBeliefStatusFromGatewayAuth(authContext, input) {
19196
19186
  }
19197
19187
  function updateBeliefRationaleFromGatewayAuth(authContext, input) {
19198
19188
  const externalNodeId = input.id ?? input.nodeId ?? input.beliefId;
19199
- return authContext.convex.mutation(api.epistemicBeliefs.updateRationale, {
19189
+ return authContext.convex.mutation(api.beliefs.updateRationale, {
19200
19190
  nodeId: resolveBeliefNodeId(input),
19201
19191
  rationale: input.rationale,
19202
19192
  userId: authContext.userId
@@ -19206,7 +19196,7 @@ function updateBeliefRationaleFromGatewayAuth(authContext, input) {
19206
19196
  }));
19207
19197
  }
19208
19198
  function linkBeliefsFromGatewayAuth(authContext, input) {
19209
- return authContext.convex.mutation(api.epistemicBeliefs.linkBeliefs, {
19199
+ return authContext.convex.mutation(api.beliefs.linkBeliefs, {
19210
19200
  fromNodeId: resolveExternalId(input.fromNodeId) ?? "",
19211
19201
  toNodeId: resolveExternalId(input.toNodeId) ?? "",
19212
19202
  edgeType: input.edgeType,
@@ -19216,7 +19206,7 @@ function linkBeliefsFromGatewayAuth(authContext, input) {
19216
19206
  });
19217
19207
  }
19218
19208
  function unlinkBeliefEvidenceFromGatewayAuth(authContext, input) {
19219
- return authContext.convex.mutation(api.epistemicBeliefs.unlinkEvidence, {
19209
+ return authContext.convex.mutation(api.beliefs.unlinkEvidence, {
19220
19210
  beliefNodeId: input.beliefNodeId ?? resolveExternalId(input.beliefId) ?? resolveExternalId(input.nodeId) ?? "",
19221
19211
  insightId: resolveExternalId(input.insightId ?? input.evidenceId) ?? "",
19222
19212
  userId: authContext.userId
@@ -19224,7 +19214,7 @@ function unlinkBeliefEvidenceFromGatewayAuth(authContext, input) {
19224
19214
  }
19225
19215
  function updateBeliefCriticalityFromGatewayAuth(authContext, input) {
19226
19216
  const externalNodeId = input.id ?? input.nodeId ?? input.beliefId;
19227
- return authContext.convex.mutation(api.epistemicBeliefs.updateCriticality, {
19217
+ return authContext.convex.mutation(api.beliefs.updateCriticality, {
19228
19218
  nodeId: resolveBeliefNodeId(input),
19229
19219
  criticality: input.criticality,
19230
19220
  userId: authContext.userId
@@ -19234,7 +19224,7 @@ function updateBeliefCriticalityFromGatewayAuth(authContext, input) {
19234
19224
  }));
19235
19225
  }
19236
19226
  function batchUpdateBeliefCriticalityFromGatewayAuth(authContext, input) {
19237
- return authContext.convex.mutation(api.epistemicBeliefs.batchUpdateCriticality, {
19227
+ return authContext.convex.mutation(api.beliefs.batchUpdateCriticality, {
19238
19228
  updates: input.updates.map((update) => ({
19239
19229
  ...update,
19240
19230
  beliefId: resolveExternalId(update.beliefId) ?? update.beliefId,
@@ -19249,7 +19239,7 @@ function batchUpdateBeliefCriticalityFromGatewayAuth(authContext, input) {
19249
19239
  });
19250
19240
  }
19251
19241
  function reassignBeliefsTopicFromGatewayAuth(authContext, input) {
19252
- return authContext.convex.mutation(api.epistemicBeliefs.reassignBeliefsTopic, {
19242
+ return authContext.convex.mutation(api.beliefs.reassignBeliefsTopic, {
19253
19243
  beliefNodeIds: (input.beliefNodeIds ?? input.beliefIds ?? []).map(
19254
19244
  (id) => resolveExternalId(id) ?? id
19255
19245
  ),
@@ -19545,7 +19535,7 @@ async function emitContradictionEventFromGatewayAuth(authContext, args) {
19545
19535
  function createGatewayContradictionsPort(authContext) {
19546
19536
  return {
19547
19537
  fetchBelief(rawId) {
19548
- return authContext.convex.query(api.epistemicBeliefs.getById, {
19538
+ return authContext.convex.query(api.beliefs.getById, {
19549
19539
  beliefId: rawId
19550
19540
  });
19551
19541
  },
@@ -19867,7 +19857,7 @@ async function fetchNodeWithQuery(runQuery, id) {
19867
19857
  const rawId = resolveNodeId(id);
19868
19858
  const byNodeId = await queryWithFallback(
19869
19859
  `fetchNodeWithQuery local id lookup for ${id}`,
19870
- () => runQuery(api.epistemicNodes.get, {
19860
+ () => runQuery(api.nodes.get, {
19871
19861
  nodeId: rawId
19872
19862
  }),
19873
19863
  null
@@ -19877,7 +19867,7 @@ async function fetchNodeWithQuery(runQuery, id) {
19877
19867
  }
19878
19868
  return await queryWithFallback(
19879
19869
  `fetchNodeWithQuery global id lookup for ${id}`,
19880
- () => runQuery(api.epistemicNodes.getByGlobalId, {
19870
+ () => runQuery(api.nodes.getByGlobalId, {
19881
19871
  globalId: id
19882
19872
  }),
19883
19873
  null
@@ -19965,7 +19955,7 @@ function createGatewayEdgesPort(authContext) {
19965
19955
  input.targetRawId
19966
19956
  );
19967
19957
  const inferredTopicId = input.topicId ?? resolveTopicIdFromNode(sourceNode) ?? resolveTopicIdFromNode(targetNode);
19968
- return authContext.convex.mutation(api.epistemicEdges.create, {
19958
+ return authContext.convex.mutation(api.edges.create, {
19969
19959
  fromNodeId: input.sourceRawId,
19970
19960
  toNodeId: input.targetRawId,
19971
19961
  edgeType: input.edgeType,
@@ -19990,7 +19980,7 @@ function createGatewayEdgesPort(authContext) {
19990
19980
  "list"
19991
19981
  );
19992
19982
  const rows = await authContext.convex.query(
19993
- api.epistemicEdges.getBySourceNode,
19983
+ api.edges.getBySourceNode,
19994
19984
  {
19995
19985
  sourceNodeId: args.sourceRawId,
19996
19986
  edgeType: args.edgeType
@@ -20032,7 +20022,7 @@ function traverseEdgesFromGatewayAuth(authContext, input) {
20032
20022
  return traverseEdges(createGatewayEdgesPort(authContext), input);
20033
20023
  }
20034
20024
  function updateEdgeFromGatewayAuth(authContext, input) {
20035
- return authContext.convex.mutation(api.epistemicEdges.update, {
20025
+ return authContext.convex.mutation(api.edges.update, {
20036
20026
  edgeId: resolveExternalId2(input.edgeId) ?? input.edgeId,
20037
20027
  weight: input.weight,
20038
20028
  confidence: input.confidence,
@@ -20042,13 +20032,13 @@ function updateEdgeFromGatewayAuth(authContext, input) {
20042
20032
  });
20043
20033
  }
20044
20034
  function removeEdgeFromGatewayAuth(authContext, input) {
20045
- return authContext.convex.mutation(api.epistemicEdges.remove, {
20035
+ return authContext.convex.mutation(api.edges.remove, {
20046
20036
  edgeId: resolveExternalId2(input.edgeId) ?? input.edgeId,
20047
20037
  userId: authContext.userId
20048
20038
  });
20049
20039
  }
20050
20040
  function removeEdgesBetweenFromGatewayAuth(authContext, input) {
20051
- return authContext.convex.mutation(api.epistemicEdges.removeBetween, {
20041
+ return authContext.convex.mutation(api.edges.removeBetween, {
20052
20042
  fromNodeId: resolveExternalId2(input.fromNodeId) ?? input.fromNodeId,
20053
20043
  toNodeId: resolveExternalId2(input.toNodeId) ?? input.toNodeId,
20054
20044
  edgeType: input.edgeType,
@@ -20056,7 +20046,7 @@ function removeEdgesBetweenFromGatewayAuth(authContext, input) {
20056
20046
  });
20057
20047
  }
20058
20048
  function batchCreateEdgesFromGatewayAuth(authContext, input) {
20059
- return authContext.convex.mutation(api.epistemicEdges.batchCreate, {
20049
+ return authContext.convex.mutation(api.edges.batchCreate, {
20060
20050
  edges: input.edges.map((edge) => ({
20061
20051
  globalId: edge.globalId ?? randomUUID(),
20062
20052
  fromNodeId: resolveExternalId2(edge.fromNodeId ?? edge.sourceId) ?? edge.fromNodeId ?? edge.sourceId ?? "",
@@ -20075,7 +20065,7 @@ function batchCreateEdgesFromGatewayAuth(authContext, input) {
20075
20065
  });
20076
20066
  }
20077
20067
  function deleteEdgesFromGatewayAuth(authContext, input) {
20078
- return authContext.convex.mutation(api.epistemicEdges.deleteEdges, {
20068
+ return authContext.convex.mutation(api.edges.deleteEdges, {
20079
20069
  edgeIds: input.edgeIds.map((edgeId) => resolveExternalId2(edgeId) ?? edgeId),
20080
20070
  userId: authContext.userId
20081
20071
  });
@@ -20403,14 +20393,14 @@ function resolveExternalId3(value) {
20403
20393
  }
20404
20394
  }
20405
20395
  async function resolveEvidenceTopicIdWithGatewayAuth(authContext, evidenceId) {
20406
- const evidence = await authContext.convex.query(api.epistemicEvidence.getById, {
20396
+ const evidence = await authContext.convex.query(api.evidence.getById, {
20407
20397
  evidenceId,
20408
20398
  nodeId: evidenceId
20409
20399
  });
20410
20400
  return readString8(evidence?.topicId);
20411
20401
  }
20412
20402
  async function resolveEvidenceNodeIdWithGatewayAuth(authContext, evidenceId) {
20413
- const evidence = await authContext.convex.query(api.epistemicEvidence.getById, {
20403
+ const evidence = await authContext.convex.query(api.evidence.getById, {
20414
20404
  evidenceId,
20415
20405
  nodeId: evidenceId
20416
20406
  });
@@ -20438,20 +20428,20 @@ async function emitEvidenceEventFromGatewayAuth(authContext, args) {
20438
20428
  function createGatewayEvidencePort(authContext) {
20439
20429
  return {
20440
20430
  fetchEvidence(rawId) {
20441
- return authContext.convex.query(api.epistemicEvidence.getById, {
20431
+ return authContext.convex.query(api.evidence.getById, {
20442
20432
  evidenceId: rawId,
20443
20433
  nodeId: rawId
20444
20434
  });
20445
20435
  },
20446
20436
  listEvidenceByTopic(args) {
20447
- return authContext.convex.query(api.epistemicEvidence.getByTopic, {
20437
+ return authContext.convex.query(api.evidence.getByTopic, {
20448
20438
  topicId: args.topicId,
20449
20439
  userId: authContext.userId,
20450
20440
  limit: args.limit
20451
20441
  });
20452
20442
  },
20453
20443
  listEvidenceForBelief(rawBeliefId) {
20454
- return authContext.convex.query(api.epistemicEvidence.getForBelief, {
20444
+ return authContext.convex.query(api.evidence.getForBelief, {
20455
20445
  beliefNodeId: rawBeliefId
20456
20446
  });
20457
20447
  },
@@ -20464,7 +20454,7 @@ function createGatewayEvidencePort(authContext) {
20464
20454
  );
20465
20455
  },
20466
20456
  async createEvidence(input) {
20467
- const created = await authContext.convex.mutation(api.epistemicEvidence.create, {
20457
+ const created = await authContext.convex.mutation(api.evidence.create, {
20468
20458
  topicId: input.topicId,
20469
20459
  text: input.text,
20470
20460
  title: input.title,
@@ -20497,7 +20487,7 @@ function createGatewayEvidencePort(authContext) {
20497
20487
  ...linkArgs
20498
20488
  });
20499
20489
  } else {
20500
- await authContext.convex.mutation(api.epistemicBeliefs.linkEvidence, {
20490
+ await authContext.convex.mutation(api.beliefs.linkEvidence, {
20501
20491
  beliefNodeId: input.target.rawId,
20502
20492
  insightId: rawId,
20503
20493
  type: input.weight < 0 ? "contradicting" : "supporting",
@@ -20508,7 +20498,7 @@ function createGatewayEvidencePort(authContext) {
20508
20498
  return created;
20509
20499
  },
20510
20500
  linkEvidenceToBelief(input) {
20511
- return authContext.convex.mutation(api.epistemicBeliefs.linkEvidence, {
20501
+ return authContext.convex.mutation(api.beliefs.linkEvidence, {
20512
20502
  beliefNodeId: input.targetRawId,
20513
20503
  insightId: input.evidenceRawId,
20514
20504
  type: input.weight < 0 ? "contradicting" : "supporting",
@@ -20640,7 +20630,7 @@ async function updateEvidenceStatusFromGatewayAuth(authContext, input) {
20640
20630
  input.id ?? input.nodeId ?? input.evidenceId ?? input.insightId ?? ""
20641
20631
  ) ?? ""
20642
20632
  );
20643
- return authContext.convex.mutation(api.epistemicEvidence.updateStatus, {
20633
+ return authContext.convex.mutation(api.evidence.updateStatus, {
20644
20634
  nodeId: resolvedNodeId ?? input.nodeId ?? input.id,
20645
20635
  status: input.status,
20646
20636
  userId: authContext.userId
@@ -20650,7 +20640,7 @@ function updateEvidenceFromGatewayAuth(authContext, input) {
20650
20640
  const evidenceId = resolveExternalId3(
20651
20641
  input.id ?? input.evidenceId ?? input.insightId ?? input.nodeId ?? ""
20652
20642
  ) ?? "";
20653
- return authContext.convex.mutation(api.epistemicEvidence.update, {
20643
+ return authContext.convex.mutation(api.evidence.update, {
20654
20644
  insightId: evidenceId,
20655
20645
  text: input.text,
20656
20646
  kind: input.kind,
@@ -20664,7 +20654,7 @@ function flagEvidenceAsIncorrectFromGatewayAuth(authContext, input) {
20664
20654
  const evidenceId = resolveExternalId3(
20665
20655
  input.id ?? input.evidenceId ?? input.insightId ?? input.nodeId ?? ""
20666
20656
  ) ?? "";
20667
- return authContext.convex.mutation(api.epistemicEvidence.flagAsIncorrect, {
20657
+ return authContext.convex.mutation(api.evidence.flagAsIncorrect, {
20668
20658
  insightId: evidenceId,
20669
20659
  reason: input.reason,
20670
20660
  suggestedCorrection: input.suggestedCorrection,
@@ -20675,7 +20665,7 @@ function removeEvidenceFromGatewayAuth(authContext, input) {
20675
20665
  const evidenceId = resolveExternalId3(
20676
20666
  input.id ?? input.evidenceId ?? input.insightId ?? input.nodeId ?? ""
20677
20667
  ) ?? "";
20678
- return authContext.convex.mutation(api.epistemicEvidence.remove, {
20668
+ return authContext.convex.mutation(api.evidence.remove, {
20679
20669
  insightId: evidenceId,
20680
20670
  userId: authContext.userId
20681
20671
  });
@@ -20687,7 +20677,7 @@ async function updateEvidenceVerificationStatusFromGatewayAuth(authContext, inpu
20687
20677
  input.id ?? input.nodeId ?? input.evidenceId ?? input.insightId ?? ""
20688
20678
  ) ?? ""
20689
20679
  );
20690
- return authContext.convex.mutation(api.epistemicEvidence.updateVerificationStatus, {
20680
+ return authContext.convex.mutation(api.evidence.updateVerificationStatus, {
20691
20681
  nodeId: resolvedNodeId ?? input.nodeId ?? input.id,
20692
20682
  verificationHash: input.verificationHash,
20693
20683
  verificationStatus: input.verificationStatus,
@@ -21271,7 +21261,7 @@ function isRecord5(value) {
21271
21261
  }
21272
21262
  async function resolveQuestionTopicIdWithGatewayAuth(authContext, questionId) {
21273
21263
  const question = await authContext.convex.query(
21274
- api.epistemicQuestions.getById,
21264
+ api.questions.getById,
21275
21265
  {
21276
21266
  questionId,
21277
21267
  nodeId: questionId
@@ -21327,20 +21317,20 @@ function normalizeLatestAnswerRecord(questionId, answer) {
21327
21317
  function createGatewayQuestionsPort(authContext) {
21328
21318
  return {
21329
21319
  fetchQuestion(rawId) {
21330
- return authContext.convex.query(api.epistemicQuestions.getById, {
21320
+ return authContext.convex.query(api.questions.getById, {
21331
21321
  questionId: rawId,
21332
21322
  nodeId: rawId
21333
21323
  });
21334
21324
  },
21335
21325
  listQuestionsByTopic(args) {
21336
- return authContext.convex.query(api.epistemicQuestions.getByTopic, {
21326
+ return authContext.convex.query(api.questions.getByTopic, {
21337
21327
  topicId: args.topicId,
21338
21328
  userId: authContext.userId,
21339
21329
  limit: args.limit
21340
21330
  });
21341
21331
  },
21342
21332
  createQuestion(input) {
21343
- return authContext.convex.mutation(api.epistemicQuestions.create, {
21333
+ return authContext.convex.mutation(api.questions.create, {
21344
21334
  topicId: input.topicId,
21345
21335
  question: input.text,
21346
21336
  priority: input.priority,
@@ -21350,7 +21340,7 @@ function createGatewayQuestionsPort(authContext) {
21350
21340
  },
21351
21341
  refineQuestion(input) {
21352
21342
  return authContext.convex.mutation(
21353
- api.epistemicQuestions.updateQuestion,
21343
+ api.questions.updateQuestion,
21354
21344
  {
21355
21345
  questionId: input.questionRawId,
21356
21346
  question: input.text
@@ -21358,14 +21348,14 @@ function createGatewayQuestionsPort(authContext) {
21358
21348
  );
21359
21349
  },
21360
21350
  updateQuestionStatus(input) {
21361
- return authContext.convex.mutation(api.epistemicQuestions.updateStatus, {
21351
+ return authContext.convex.mutation(api.questions.updateStatus, {
21362
21352
  questionId: input.questionRawId,
21363
21353
  status: input.status,
21364
21354
  userId: authContext.userId
21365
21355
  });
21366
21356
  },
21367
21357
  createAnswer(input) {
21368
- return authContext.convex.mutation(api.epistemicAnswers.create, {
21358
+ return authContext.convex.mutation(api.answers.create, {
21369
21359
  questionNodeId: input.questionRawId,
21370
21360
  topicId: input.topicId,
21371
21361
  answerText: input.text,
@@ -21450,7 +21440,7 @@ async function answerQuestionFromGatewayAuth(authContext, input) {
21450
21440
  }
21451
21441
  async function getQuestionAnswerFromGatewayAuth(authContext, questionId) {
21452
21442
  const answer = await authContext.convex.query(
21453
- api.epistemicAnswers.getLatestForQuestion,
21443
+ api.answers.getLatestForQuestion,
21454
21444
  {
21455
21445
  questionNodeId: questionId
21456
21446
  }
@@ -21543,7 +21533,7 @@ function createQuestionsBatchFromGatewayAuth(authContext, input) {
21543
21533
  sourceKind: "question_batch",
21544
21534
  autoCreate: input.topicId ? false : true
21545
21535
  })).topicId;
21546
- return authContext.convex.mutation(api.epistemicQuestions.createBatch, {
21536
+ return authContext.convex.mutation(api.questions.createBatch, {
21547
21537
  topicId: resolvedTopicId,
21548
21538
  questions: input.questions.map((question) => ({
21549
21539
  ...question,
@@ -21580,7 +21570,7 @@ async function addQuestionFromGatewayAuth(authContext, input) {
21580
21570
  autoCreate: input.topicId ? false : true
21581
21571
  })).topicId;
21582
21572
  const questionId = await authContext.convex.mutation(
21583
- api.epistemicQuestions.addQuestion,
21573
+ api.questions.addQuestion,
21584
21574
  {
21585
21575
  topicId: resolvedTopicId,
21586
21576
  question: input.question ?? input.text ?? "",
@@ -21603,7 +21593,7 @@ async function addQuestionFromGatewayAuth(authContext, input) {
21603
21593
  return getQuestionFromGatewayAuth(authContext, String(questionId));
21604
21594
  }
21605
21595
  async function updateQuestionPriorityFromGatewayAuth(authContext, input) {
21606
- await authContext.convex.mutation(api.epistemicQuestions.updatePriority, {
21596
+ await authContext.convex.mutation(api.questions.updatePriority, {
21607
21597
  nodeId: normalizePrefixedId(
21608
21598
  input.id ?? input.nodeId ?? input.questionId,
21609
21599
  "que"
@@ -21618,7 +21608,7 @@ async function updateQuestionPriorityFromGatewayAuth(authContext, input) {
21618
21608
  }
21619
21609
  function advanceQuestionToConvictionFromGatewayAuth(authContext, input) {
21620
21610
  return authContext.convex.mutation(
21621
- api.epistemicQuestions.advanceToConviction,
21611
+ api.questions.advanceToConviction,
21622
21612
  {
21623
21613
  questionId: normalizePrefixedId(
21624
21614
  input.questionId ?? input.id ?? input.nodeId,
@@ -21630,7 +21620,7 @@ function advanceQuestionToConvictionFromGatewayAuth(authContext, input) {
21630
21620
  );
21631
21621
  }
21632
21622
  function updateQuestionConvictionFromGatewayAuth(authContext, input) {
21633
- return authContext.convex.mutation(api.epistemicQuestions.updateConviction, {
21623
+ return authContext.convex.mutation(api.questions.updateConviction, {
21634
21624
  questionId: normalizePrefixedId(
21635
21625
  input.questionId ?? input.id ?? input.nodeId,
21636
21626
  "que"
@@ -21643,7 +21633,7 @@ function updateQuestionConvictionFromGatewayAuth(authContext, input) {
21643
21633
  }
21644
21634
  function finalizeQuestionConvictionFromGatewayAuth(authContext, input) {
21645
21635
  return authContext.convex.mutation(
21646
- api.epistemicQuestions.finalizeConviction,
21636
+ api.questions.finalizeConviction,
21647
21637
  {
21648
21638
  questionId: normalizePrefixedId(
21649
21639
  input.questionId ?? input.id ?? input.nodeId,
@@ -21660,7 +21650,7 @@ function finalizeQuestionConvictionFromGatewayAuth(authContext, input) {
21660
21650
  }
21661
21651
  async function updateQuestionFromGatewayAuth(authContext, input) {
21662
21652
  const questionId = normalizePrefixedId(input.questionId ?? input.id ?? input.nodeId, "que") ?? "";
21663
- await authContext.convex.mutation(api.epistemicQuestions.updateQuestion, {
21653
+ await authContext.convex.mutation(api.questions.updateQuestion, {
21664
21654
  questionId,
21665
21655
  question: input.question ?? input.text,
21666
21656
  category: input.category,
@@ -21669,7 +21659,7 @@ async function updateQuestionFromGatewayAuth(authContext, input) {
21669
21659
  return getQuestionFromGatewayAuth(authContext, questionId);
21670
21660
  }
21671
21661
  function deleteQuestionFromGatewayAuth(authContext, input) {
21672
- return authContext.convex.mutation(api.epistemicQuestions.deleteQuestion, {
21662
+ return authContext.convex.mutation(api.questions.deleteQuestion, {
21673
21663
  questionId: normalizePrefixedId(
21674
21664
  input.questionId ?? input.id ?? input.nodeId,
21675
21665
  "que"
@@ -21738,13 +21728,13 @@ function normalizeGraphEdge(row) {
21738
21728
  }
21739
21729
  async function fetchGraphNodeByIdentifier(authContext, input) {
21740
21730
  if (input.nodeId) {
21741
- const node = await authContext.convex.query(api.epistemicNodes.get, {
21731
+ const node = await authContext.convex.query(api.nodes.get, {
21742
21732
  nodeId: input.nodeId
21743
21733
  });
21744
21734
  return node ? normalizeGraphNode(node) : null;
21745
21735
  }
21746
21736
  if (input.globalId) {
21747
- const node = await authContext.convex.query(api.epistemicNodes.getByGlobalId, {
21737
+ const node = await authContext.convex.query(api.nodes.getByGlobalId, {
21748
21738
  globalId: input.globalId
21749
21739
  });
21750
21740
  return node ? normalizeGraphNode(node) : null;
@@ -21922,7 +21912,7 @@ function createGatewayGraphPort(authContext) {
21922
21912
  return page.beliefs;
21923
21913
  },
21924
21914
  async fetchBelief(input) {
21925
- const belief = await authContext.convex.query(api.epistemicBeliefs.getById, {
21915
+ const belief = await authContext.convex.query(api.beliefs.getById, {
21926
21916
  beliefId: input.beliefId,
21927
21917
  nodeId: input.beliefId
21928
21918
  });
@@ -21936,7 +21926,7 @@ function createGatewayGraphPort(authContext) {
21936
21926
  return page.questions;
21937
21927
  },
21938
21928
  async listTestingEdges(input) {
21939
- const rows = await authContext.convex.query(api.epistemicEdges.getByTopicAndType, {
21929
+ const rows = await authContext.convex.query(api.edges.getByTopicAndType, {
21940
21930
  topicId: input.topicId,
21941
21931
  edgeType: "tests"
21942
21932
  });
@@ -21980,7 +21970,7 @@ async function listGraphNodesFromGatewayAuth(authContext, input) {
21980
21970
  if (!topicId) {
21981
21971
  throw new Error("[graph] topicId is required to list graph nodes.");
21982
21972
  }
21983
- const rows = await authContext.convex.query(api.epistemicNodes.getByTopic, {
21973
+ const rows = await authContext.convex.query(api.nodes.getByTopic, {
21984
21974
  topicId,
21985
21975
  userId: authContext.userId,
21986
21976
  limit: normalizeLimit(input.limit, 250, 1e3)
@@ -21993,7 +21983,7 @@ async function listGraphEdgesFromGatewayAuth(authContext, input) {
21993
21983
  if (!topicId) {
21994
21984
  throw new Error("[graph] topicId is required to list graph edges.");
21995
21985
  }
21996
- const rows = await authContext.convex.query(api.epistemicEdges.getByTopic, {
21986
+ const rows = await authContext.convex.query(api.edges.getByTopic, {
21997
21987
  topicId,
21998
21988
  userId: authContext.userId,
21999
21989
  limit: normalizeLimit(input.limit, 500, 2e3)
@@ -23825,21 +23815,21 @@ function createGatewayTopicsPort(authContext) {
23825
23815
  });
23826
23816
  },
23827
23817
  listBeliefsByTopic(args) {
23828
- return authContext.convex.query(api.epistemicBeliefs.getByTopic, {
23818
+ return authContext.convex.query(api.beliefs.getByTopic, {
23829
23819
  topicId: args.topicId,
23830
23820
  userId: authContext.userId,
23831
23821
  limit: args.limit
23832
23822
  });
23833
23823
  },
23834
23824
  listQuestionsByTopic(args) {
23835
- return authContext.convex.query(api.epistemicQuestions.getByTopic, {
23825
+ return authContext.convex.query(api.questions.getByTopic, {
23836
23826
  topicId: args.topicId,
23837
23827
  userId: authContext.userId,
23838
23828
  limit: args.limit
23839
23829
  });
23840
23830
  },
23841
23831
  listEvidenceByTopic(args) {
23842
- return authContext.convex.query(api.epistemicEvidence.getByTopic, {
23832
+ return authContext.convex.query(api.evidence.getByTopic, {
23843
23833
  topicId: args.topicId,
23844
23834
  userId: authContext.userId,
23845
23835
  limit: args.limit
@@ -24757,7 +24747,7 @@ function createGatewayWorktreesPort(authContext) {
24757
24747
  scoreBeliefOutcome(args) {
24758
24748
  const opinion = toSubjectiveLogicOpinion(args.confidence);
24759
24749
  return authContext.convex.mutation(
24760
- api.epistemicBeliefs.modulateConfidence,
24750
+ api.beliefs.modulateConfidence,
24761
24751
  {
24762
24752
  nodeId: args.beliefRawId,
24763
24753
  trigger: "worktree_outcome",
@@ -27432,6 +27422,16 @@ var PERMIT_MEMBERSHIP_ROLES = /* @__PURE__ */ new Set([
27432
27422
  "platform_admin",
27433
27423
  "workspace_admin"
27434
27424
  ]);
27425
+ var PERMIT_WORKSPACE_ROLES = /* @__PURE__ */ new Set([
27426
+ "workspace_owner",
27427
+ "workspace_admin",
27428
+ "workspace_member",
27429
+ "workspace_viewer"
27430
+ ]);
27431
+ var PERMIT_DEPLOYMENT_ROLES = /* @__PURE__ */ new Set([
27432
+ "deployment_admin",
27433
+ "deployment_operator"
27434
+ ]);
27435
27435
  var CLERK_WEBHOOK_SECRETS = [
27436
27436
  "LUCERN_CLERK_WEBHOOK_SECRET",
27437
27437
  "CLERK_WEBHOOK_SECRET",
@@ -27453,8 +27453,7 @@ function readNumber18(value) {
27453
27453
  }
27454
27454
  return void 0;
27455
27455
  }
27456
- var PERMIT_USER_KEY_PATTERN = /^[A-Za-z0-9|@+\-._]+$/;
27457
- var PERMIT_USER_KEY_ESCAPE_SENTINEL = "|";
27456
+ var CLERK_USER_ID_PATTERN = /^user_[A-Za-z0-9]+$/;
27458
27457
  function asRecord26(value) {
27459
27458
  return isRecord8(value) ? value : {};
27460
27459
  }
@@ -27469,14 +27468,14 @@ function encodeBase64(bytes) {
27469
27468
  }
27470
27469
  return btoa(binary);
27471
27470
  }
27472
- function permitUserKeyForPrincipalId(principalId) {
27473
- const trimmed = principalId.trim();
27474
- if (PERMIT_USER_KEY_PATTERN.test(trimmed) && !trimmed.includes(PERMIT_USER_KEY_ESCAPE_SENTINEL)) {
27475
- return trimmed;
27471
+ function permitUserKeyForClerkUserId(userId) {
27472
+ const trimmed = userId.trim();
27473
+ if (!CLERK_USER_ID_PATTERN.test(trimmed)) {
27474
+ throw new Error(
27475
+ `Clerk webhook user id must be a canonical Clerk user ID. Received "${userId}".`
27476
+ );
27476
27477
  }
27477
- return Array.from(trimmed).map(
27478
- (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}`
27479
- ).join("");
27478
+ return trimmed;
27480
27479
  }
27481
27480
  function compactRecord5(value) {
27482
27481
  return Object.fromEntries(
@@ -27565,9 +27564,12 @@ async function upsertPermitTenant(args) {
27565
27564
  const tenantPayload = {
27566
27565
  name: args.tenantName ?? args.tenantKey,
27567
27566
  attributes: compactRecord5({
27567
+ canonicalTenantId: args.clerkOrganizationId,
27568
+ canonicalTenantProvider: "clerk",
27568
27569
  clerkOrganizationId: args.clerkOrganizationId,
27569
27570
  clerkOrganizationSlug: args.clerkOrganizationSlug,
27570
- mcTenantKey: args.tenantKey,
27571
+ mcTenantId: args.mcTenantId,
27572
+ mcTenantSlug: args.mcTenantSlug,
27571
27573
  sourceType: "organization",
27572
27574
  sourceEvent: args.eventType,
27573
27575
  eventAt: args.eventAt,
@@ -27586,16 +27588,192 @@ async function upsertPermitTenant(args) {
27586
27588
  ...tenantPayload
27587
27589
  });
27588
27590
  }
27591
+ async function upsertPermitResourceInstance(args) {
27592
+ const permit = getPermitClient();
27593
+ const resourceInstance = `${args.resource}:${args.key}`;
27594
+ const payload = {
27595
+ attributes: compactRecord5(args.attributes)
27596
+ };
27597
+ try {
27598
+ return await permit.api.resourceInstances.update(resourceInstance, payload);
27599
+ } catch (error) {
27600
+ if (!isNotFound(error)) {
27601
+ throw error;
27602
+ }
27603
+ }
27604
+ try {
27605
+ return await permit.api.resourceInstances.create({
27606
+ key: args.key,
27607
+ tenant: args.tenantKey,
27608
+ resource: args.resource,
27609
+ attributes: payload.attributes
27610
+ });
27611
+ } catch (error) {
27612
+ if (!isConflict(error)) {
27613
+ throw error;
27614
+ }
27615
+ }
27616
+ return await permit.api.resourceInstances.update(resourceInstance, payload);
27617
+ }
27618
+ async function createPermitRelationshipTuple(args) {
27619
+ const permit = getPermitClient();
27620
+ const relationshipTuples = permit.api.relationshipTuples;
27621
+ if (!relationshipTuples || typeof relationshipTuples.create !== "function") {
27622
+ throw new Error("Permit SDK does not expose relationship tuple creation");
27623
+ }
27624
+ try {
27625
+ return await relationshipTuples.create({
27626
+ subject: args.subject,
27627
+ relation: args.relation,
27628
+ object: args.object,
27629
+ tenant: args.tenant
27630
+ });
27631
+ } catch (error) {
27632
+ if (isConflict(error)) {
27633
+ return { alreadyCreated: true };
27634
+ }
27635
+ throw error;
27636
+ }
27637
+ }
27638
+ async function upsertPermitWorkspaceProjection(args) {
27639
+ const workspaceKey = workspacePermitKey({
27640
+ tenantKey: args.tenantKey,
27641
+ workspace: args.workspace
27642
+ });
27643
+ if (!workspaceKey) {
27644
+ return void 0;
27645
+ }
27646
+ return await upsertPermitResourceInstance({
27647
+ resource: "workspace",
27648
+ key: workspaceKey,
27649
+ tenantKey: args.tenantKey,
27650
+ attributes: {
27651
+ canonicalTenantId: args.tenantKey,
27652
+ canonicalTenantProvider: "clerk",
27653
+ clerkOrganizationId: args.tenantKey,
27654
+ mcTenantId: args.mcTenantId,
27655
+ mcTenantSlug: args.mcTenantSlug,
27656
+ mcWorkspaceId: readString28(args.workspace._id),
27657
+ workspaceSlug: readString28(args.workspace.slug),
27658
+ workspaceKey: readString28(args.workspace.key),
27659
+ name: readString28(args.workspace.name),
27660
+ status: readString28(args.workspace.status),
27661
+ sourceType: "clerk_webhook_workspace_projection",
27662
+ sourceEvent: args.eventType,
27663
+ eventAt: args.eventAt,
27664
+ actorId: args.actorId
27665
+ }
27666
+ });
27667
+ }
27668
+ async function upsertPermitWorkspaceRelationship(args) {
27669
+ return await createPermitRelationshipTuple({
27670
+ subject: `workspace:${args.workspaceKey}`,
27671
+ relation: "belongs_to",
27672
+ object: `tenant:${args.tenantKey}`,
27673
+ tenant: args.tenantKey
27674
+ });
27675
+ }
27676
+ function deploymentPermitKey(args) {
27677
+ const workspaceKey = workspacePermitKey({
27678
+ tenantKey: args.tenantKey,
27679
+ workspace: args.workspace
27680
+ });
27681
+ const environment = slugForPermitKey(args.environment);
27682
+ if (!workspaceKey || !environment) {
27683
+ return void 0;
27684
+ }
27685
+ return `${workspaceKey}--${environment}`;
27686
+ }
27687
+ async function upsertPermitDeploymentProjection(args) {
27688
+ const deploymentKey = deploymentPermitKey({
27689
+ tenantKey: args.tenantKey,
27690
+ workspace: args.workspace,
27691
+ environment: args.environment
27692
+ });
27693
+ if (!deploymentKey) {
27694
+ return void 0;
27695
+ }
27696
+ await upsertPermitResourceInstance({
27697
+ resource: "deployment",
27698
+ key: deploymentKey,
27699
+ tenantKey: args.tenantKey,
27700
+ attributes: {
27701
+ canonicalTenantId: args.tenantKey,
27702
+ canonicalTenantProvider: "clerk",
27703
+ clerkOrganizationId: args.tenantKey,
27704
+ mcTenantId: args.mcTenantId,
27705
+ mcTenantSlug: args.mcTenantSlug,
27706
+ mcWorkspaceId: readString28(args.workspace._id),
27707
+ workspaceKey: args.workspaceKey,
27708
+ workspaceSlug: readString28(args.workspace.slug),
27709
+ environment: args.environment,
27710
+ target: readString28(args.deployment.target) ?? "appDeployment",
27711
+ url: readString28(args.deployment.url),
27712
+ credentialRef: readString28(args.deployment.credentialRef),
27713
+ hasCredentialRef: Boolean(readString28(args.deployment.credentialRef)),
27714
+ sourceType: "clerk_webhook_deployment_projection",
27715
+ sourceEvent: args.eventType,
27716
+ eventAt: args.eventAt,
27717
+ actorId: args.actorId
27718
+ }
27719
+ });
27720
+ await createPermitRelationshipTuple({
27721
+ subject: `deployment:${deploymentKey}`,
27722
+ relation: "belongs_to",
27723
+ object: `workspace:${args.workspaceKey}`,
27724
+ tenant: args.tenantKey
27725
+ });
27726
+ return { deploymentKey };
27727
+ }
27728
+ async function upsertPermitDeploymentProjectionsForWorkspace(args) {
27729
+ const deployments = asRecord26(args.workspace.deployments);
27730
+ const deploymentKeys = [];
27731
+ for (const [environment, deployment] of Object.entries(deployments)) {
27732
+ if (!isRecord8(deployment)) {
27733
+ continue;
27734
+ }
27735
+ const projected = await upsertPermitDeploymentProjection({
27736
+ tenantKey: args.tenantKey,
27737
+ mcTenantId: args.mcTenantId,
27738
+ mcTenantSlug: args.mcTenantSlug,
27739
+ workspace: args.workspace,
27740
+ workspaceKey: args.workspaceKey,
27741
+ environment,
27742
+ deployment,
27743
+ eventType: args.eventType,
27744
+ eventAt: args.eventAt,
27745
+ actorId: args.actorId
27746
+ });
27747
+ if (projected?.deploymentKey) {
27748
+ deploymentKeys.push(projected.deploymentKey);
27749
+ }
27750
+ }
27751
+ return deploymentKeys;
27752
+ }
27589
27753
  async function syncPermitUser(args) {
27590
27754
  const permit = getPermitClient();
27591
27755
  return await permit.api.users.sync({
27592
- key: permitUserKeyForPrincipalId(args.userId),
27756
+ key: permitUserKeyForClerkUserId(args.userId),
27593
27757
  email: args.email,
27594
27758
  attributes: compactRecord5({
27595
27759
  sourceType: "clerk_webhook_user",
27596
27760
  sourceEvent: args.eventType,
27597
27761
  clerkStatus: args.eventType,
27598
27762
  clerkDisplayName: args.displayName,
27763
+ clerkAliases: [
27764
+ compactRecord5({
27765
+ provider: "clerk",
27766
+ externalSubjectId: args.userId,
27767
+ email: args.email
27768
+ })
27769
+ ],
27770
+ aliases: [
27771
+ compactRecord5({
27772
+ provider: "clerk",
27773
+ externalSubjectId: args.userId,
27774
+ email: args.email
27775
+ })
27776
+ ],
27599
27777
  eventAt: args.eventAt,
27600
27778
  actorId: args.actorId
27601
27779
  })
@@ -27603,7 +27781,7 @@ async function syncPermitUser(args) {
27603
27781
  }
27604
27782
  async function upsertPermitTenantMembershipRole(args) {
27605
27783
  const permit = getPermitClient();
27606
- const permitUserId = permitUserKeyForPrincipalId(args.userId);
27784
+ const permitUserId = permitUserKeyForClerkUserId(args.userId);
27607
27785
  const existing = readRoleAssignments(
27608
27786
  await permit.api.roleAssignments.list({
27609
27787
  user: permitUserId,
@@ -27645,6 +27823,127 @@ async function upsertPermitTenantMembershipRole(args) {
27645
27823
  throw error;
27646
27824
  }
27647
27825
  }
27826
+ function workspaceRoleForTenantMembership(role) {
27827
+ if (role === "platform_admin" || role === "tenant_admin") {
27828
+ return "workspace_owner";
27829
+ }
27830
+ if (role === "workspace_admin") {
27831
+ return "workspace_admin";
27832
+ }
27833
+ if (role === "editor" || role === "service_agent") {
27834
+ return "workspace_member";
27835
+ }
27836
+ return "workspace_viewer";
27837
+ }
27838
+ function deploymentRoleForTenantMembership(role) {
27839
+ const workspaceRole = workspaceRoleForTenantMembership(role);
27840
+ if (workspaceRole === "workspace_owner") {
27841
+ return "deployment_admin";
27842
+ }
27843
+ if (workspaceRole === "workspace_admin") {
27844
+ return "deployment_operator";
27845
+ }
27846
+ return null;
27847
+ }
27848
+ async function upsertPermitWorkspaceMembershipRole(args) {
27849
+ const permit = getPermitClient();
27850
+ const permitUserId = permitUserKeyForClerkUserId(args.userId);
27851
+ const workspaceRole = workspaceRoleForTenantMembership(args.role);
27852
+ const existing = readRoleAssignments(
27853
+ await permit.api.roleAssignments.list({
27854
+ user: permitUserId,
27855
+ tenant: args.tenantKey,
27856
+ resourceInstance: args.resourceInstance,
27857
+ perPage: 100
27858
+ })
27859
+ );
27860
+ await Promise.all(
27861
+ existing.map((assignment2) => {
27862
+ const role = readString28(assignment2.role);
27863
+ if (!role || !PERMIT_WORKSPACE_ROLES.has(role)) {
27864
+ return Promise.resolve();
27865
+ }
27866
+ if (roleAssignmentResourceInstance(assignment2) !== args.resourceInstance) {
27867
+ return Promise.resolve();
27868
+ }
27869
+ if (role === workspaceRole) {
27870
+ return Promise.resolve();
27871
+ }
27872
+ return unassignPermitTenantMembershipRole({
27873
+ permit,
27874
+ permitUserId,
27875
+ tenant: args.tenantKey,
27876
+ role,
27877
+ resourceInstance: args.resourceInstance
27878
+ });
27879
+ })
27880
+ );
27881
+ const assignment = {
27882
+ user: permitUserId,
27883
+ role: workspaceRole,
27884
+ tenant: args.tenantKey,
27885
+ resource_instance: args.resourceInstance
27886
+ };
27887
+ try {
27888
+ return await permit.api.roleAssignments.assign(assignment);
27889
+ } catch (error) {
27890
+ if (isConflict(error)) {
27891
+ return { alreadyAssigned: true };
27892
+ }
27893
+ throw error;
27894
+ }
27895
+ }
27896
+ async function upsertPermitDeploymentMembershipRole(args) {
27897
+ const permit = getPermitClient();
27898
+ const permitUserId = permitUserKeyForClerkUserId(args.userId);
27899
+ const deploymentRole = deploymentRoleForTenantMembership(args.role);
27900
+ const existing = readRoleAssignments(
27901
+ await permit.api.roleAssignments.list({
27902
+ user: permitUserId,
27903
+ tenant: args.tenantKey,
27904
+ resourceInstance: args.resourceInstance,
27905
+ perPage: 100
27906
+ })
27907
+ );
27908
+ await Promise.all(
27909
+ existing.map((assignment2) => {
27910
+ const role = readString28(assignment2.role);
27911
+ if (!role || !PERMIT_DEPLOYMENT_ROLES.has(role)) {
27912
+ return Promise.resolve();
27913
+ }
27914
+ if (roleAssignmentResourceInstance(assignment2) !== args.resourceInstance) {
27915
+ return Promise.resolve();
27916
+ }
27917
+ if (role === deploymentRole) {
27918
+ return Promise.resolve();
27919
+ }
27920
+ return unassignPermitTenantMembershipRole({
27921
+ permit,
27922
+ permitUserId,
27923
+ tenant: args.tenantKey,
27924
+ role,
27925
+ resourceInstance: args.resourceInstance
27926
+ });
27927
+ })
27928
+ );
27929
+ if (!deploymentRole) {
27930
+ return { skipped: "membership_role_has_no_deployment_role" };
27931
+ }
27932
+ const assignment = {
27933
+ user: permitUserId,
27934
+ role: deploymentRole,
27935
+ tenant: args.tenantKey,
27936
+ resource_instance: args.resourceInstance
27937
+ };
27938
+ try {
27939
+ return await permit.api.roleAssignments.assign(assignment);
27940
+ } catch (error) {
27941
+ if (isConflict(error)) {
27942
+ return { alreadyAssigned: true };
27943
+ }
27944
+ throw error;
27945
+ }
27946
+ }
27648
27947
  async function unassignPermitTenantMembershipRole(args) {
27649
27948
  const api2 = args.permit.api;
27650
27949
  const assignment = {
@@ -27670,7 +27969,7 @@ async function unassignPermitTenantMembershipRole(args) {
27670
27969
  }
27671
27970
  async function revokePermitTenantMembershipRoles(args) {
27672
27971
  const permit = getPermitClient();
27673
- const permitUserId = permitUserKeyForPrincipalId(args.userId);
27972
+ const permitUserId = permitUserKeyForClerkUserId(args.userId);
27674
27973
  const assignments = readRoleAssignments(
27675
27974
  await permit.api.roleAssignments.list({
27676
27975
  user: permitUserId,
@@ -27696,6 +27995,88 @@ async function revokePermitTenantMembershipRoles(args) {
27696
27995
  })
27697
27996
  );
27698
27997
  }
27998
+ async function revokePermitWorkspaceMembershipRoles(args) {
27999
+ const permit = getPermitClient();
28000
+ const permitUserId = permitUserKeyForClerkUserId(args.userId);
28001
+ const assignments = readRoleAssignments(
28002
+ await permit.api.roleAssignments.list({
28003
+ user: permitUserId,
28004
+ tenant: args.tenantKey,
28005
+ resourceInstance: args.resourceInstance,
28006
+ perPage: 100
28007
+ })
28008
+ );
28009
+ const workspaceRoles = assignments.filter(
28010
+ (assignment) => roleAssignmentResourceInstance(assignment) === args.resourceInstance && PERMIT_WORKSPACE_ROLES.has(readString28(assignment.role) ?? "")
28011
+ );
28012
+ await Promise.all(
28013
+ workspaceRoles.map((assignment) => {
28014
+ const role = readString28(assignment.role);
28015
+ if (!role) {
28016
+ return Promise.resolve();
28017
+ }
28018
+ return unassignPermitTenantMembershipRole({
28019
+ permit,
28020
+ permitUserId,
28021
+ tenant: args.tenantKey,
28022
+ role,
28023
+ resourceInstance: args.resourceInstance
28024
+ });
28025
+ })
28026
+ );
28027
+ }
28028
+ async function revokePermitDeploymentMembershipRoles(args) {
28029
+ const permit = getPermitClient();
28030
+ const permitUserId = permitUserKeyForClerkUserId(args.userId);
28031
+ const assignments = readRoleAssignments(
28032
+ await permit.api.roleAssignments.list({
28033
+ user: permitUserId,
28034
+ tenant: args.tenantKey,
28035
+ resourceInstance: args.resourceInstance,
28036
+ perPage: 100
28037
+ })
28038
+ );
28039
+ const deploymentRoles = assignments.filter(
28040
+ (assignment) => roleAssignmentResourceInstance(assignment) === args.resourceInstance && PERMIT_DEPLOYMENT_ROLES.has(readString28(assignment.role) ?? "")
28041
+ );
28042
+ await Promise.all(
28043
+ deploymentRoles.map((assignment) => {
28044
+ const role = readString28(assignment.role);
28045
+ if (!role) {
28046
+ return Promise.resolve();
28047
+ }
28048
+ return unassignPermitTenantMembershipRole({
28049
+ permit,
28050
+ permitUserId,
28051
+ tenant: args.tenantKey,
28052
+ role,
28053
+ resourceInstance: args.resourceInstance
28054
+ });
28055
+ })
28056
+ );
28057
+ }
28058
+ function tenantPermitKey(args) {
28059
+ return readString28(args.organizationId);
28060
+ }
28061
+ function workspacePermitKey(args) {
28062
+ const tenantKey = readString28(args.tenantKey);
28063
+ const workspaceKey = slugForPermitKey(
28064
+ readString28(args.workspace.slug) ?? readString28(args.workspace.key),
28065
+ readString28(args.workspace._id)
28066
+ );
28067
+ if (!tenantKey || !workspaceKey) {
28068
+ return void 0;
28069
+ }
28070
+ return `${tenantKey}--${workspaceKey}`;
28071
+ }
28072
+ function slugForPermitKey(value, fallback) {
28073
+ const raw = readString28(value) ?? readString28(fallback);
28074
+ if (!raw) {
28075
+ return void 0;
28076
+ }
28077
+ const slug = raw.toLowerCase().replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
28078
+ return slug || void 0;
28079
+ }
27699
28080
  function normalizeBase64(value) {
27700
28081
  return value.replace(/-/g, "+").replace(/_/g, "/");
27701
28082
  }
@@ -27882,12 +28263,12 @@ async function getMasterControlConvexClient2() {
27882
28263
  mcClientCache2.value = client;
27883
28264
  return client;
27884
28265
  }
27885
- async function resolveTenantByOrgSlug(args) {
27886
- if (!args.organizationSlug) {
28266
+ async function resolveTenantByClerkOrganization(args) {
28267
+ if (!args.organizationId) {
27887
28268
  return void 0;
27888
28269
  }
27889
- const tenant = await args.client.query(mcApi2.tenants.getBySlug, {
27890
- slug: args.organizationSlug
28270
+ const tenant = await args.client.query(mcApi2.tenants.getByCanonicalOrgId, {
28271
+ clerkOrganizationId: args.organizationId
27891
28272
  });
27892
28273
  if (!tenant || !isRecord8(tenant)) {
27893
28274
  return void 0;
@@ -27899,6 +28280,90 @@ async function resolveTenantByOrgSlug(args) {
27899
28280
  }
27900
28281
  return { tenantId, tenantSlug };
27901
28282
  }
28283
+ async function resolveOrProvisionTenantByClerkOrganization(args) {
28284
+ const existing = await resolveTenantByClerkOrganization({
28285
+ client: args.client,
28286
+ organizationId: args.organizationId
28287
+ });
28288
+ if (existing) {
28289
+ return { ...existing, provisioned: false };
28290
+ }
28291
+ if (args.eventType !== "organization.created") {
28292
+ return void 0;
28293
+ }
28294
+ const result = await args.client.mutation(
28295
+ mcApi2.tenants.provisionFromClerkOrganization,
28296
+ {
28297
+ clerkOrganizationId: args.organizationId,
28298
+ organizationName: args.organizationName,
28299
+ organizationSlug: args.organizationSlug,
28300
+ ownerClerkId: CLERK_USER_ID_PATTERN.test(args.actorId) ? args.actorId : void 0,
28301
+ actorClerkId: args.actorId
28302
+ }
28303
+ );
28304
+ const record = asRecord26(result);
28305
+ const tenantId = readString28(record.tenantId);
28306
+ const tenantSlug = readString28(record.slug) ?? args.organizationId;
28307
+ if (!tenantId) {
28308
+ return void 0;
28309
+ }
28310
+ return {
28311
+ tenantId,
28312
+ tenantSlug,
28313
+ provisioned: Boolean(record.created)
28314
+ };
28315
+ }
28316
+ async function listActiveTenantWorkspaces(args) {
28317
+ const workspaces2 = await args.client.query(mcApi2.workspaces.listByTenant, {
28318
+ tenantId: args.tenantId,
28319
+ status: "active"
28320
+ });
28321
+ return asArray(workspaces2).filter(isRecord8);
28322
+ }
28323
+ async function upsertPermitWorkspaceProjectionsForTenant(args) {
28324
+ const workspaces2 = await listActiveTenantWorkspaces({
28325
+ client: args.client,
28326
+ tenantId: args.tenant.tenantId
28327
+ });
28328
+ const projected = [];
28329
+ for (const workspace of workspaces2) {
28330
+ await upsertPermitWorkspaceProjection({
28331
+ tenantKey: args.tenantKey,
28332
+ mcTenantId: args.tenant.tenantId,
28333
+ mcTenantSlug: args.tenant.tenantSlug,
28334
+ workspace,
28335
+ eventType: args.eventType,
28336
+ eventAt: args.eventAt,
28337
+ actorId: args.actorId
28338
+ });
28339
+ const workspaceKey = workspacePermitKey({
28340
+ tenantKey: args.tenantKey,
28341
+ workspace
28342
+ });
28343
+ const deploymentKeys = workspaceKey ? await upsertPermitDeploymentProjectionsForWorkspace({
28344
+ tenantKey: args.tenantKey,
28345
+ mcTenantId: args.tenant.tenantId,
28346
+ mcTenantSlug: args.tenant.tenantSlug,
28347
+ workspace,
28348
+ workspaceKey,
28349
+ eventType: args.eventType,
28350
+ eventAt: args.eventAt,
28351
+ actorId: args.actorId
28352
+ }) : [];
28353
+ if (workspaceKey) {
28354
+ await upsertPermitWorkspaceRelationship({
28355
+ tenantKey: args.tenantKey,
28356
+ workspaceKey
28357
+ });
28358
+ }
28359
+ projected.push({
28360
+ workspaceId: readString28(workspace._id),
28361
+ workspaceKey,
28362
+ deploymentKeys
28363
+ });
28364
+ }
28365
+ return projected;
28366
+ }
27902
28367
  function webhookError(code, status, message, correlationId, policyTraceId, details) {
27903
28368
  return errorResponse({
27904
28369
  code,
@@ -27994,9 +28459,13 @@ async function handleClerkWebhook(args) {
27994
28459
  );
27995
28460
  }
27996
28461
  const client = await getClient();
27997
- const tenant = await resolveTenantByOrgSlug({
28462
+ const tenant = await resolveOrProvisionTenantByClerkOrganization({
27998
28463
  client,
27999
- organizationSlug: organizationIds.organizationSlug
28464
+ organizationId,
28465
+ organizationSlug: organizationIds.organizationSlug,
28466
+ organizationName: extractOrganizationName(organizationRecord),
28467
+ eventType,
28468
+ actorId
28000
28469
  });
28001
28470
  if (!tenant) {
28002
28471
  return webhookError(
@@ -28015,12 +28484,58 @@ async function handleClerkWebhook(args) {
28015
28484
  await upsertPermitTenant({
28016
28485
  clerkOrganizationId: organizationId,
28017
28486
  clerkOrganizationSlug: organizationIds.organizationSlug,
28018
- tenantKey: tenant.tenantSlug,
28487
+ mcTenantId: tenant.tenantId,
28488
+ mcTenantSlug: tenant.tenantSlug,
28489
+ tenantKey: organizationId,
28019
28490
  tenantName: extractOrganizationName(organizationRecord),
28020
28491
  eventType,
28021
28492
  eventAt: eventTimestamp,
28022
28493
  actorId
28023
28494
  });
28495
+ const workspaces2 = await upsertPermitWorkspaceProjectionsForTenant({
28496
+ client,
28497
+ tenant,
28498
+ tenantKey: organizationId,
28499
+ eventType,
28500
+ eventAt: eventTimestamp,
28501
+ actorId
28502
+ });
28503
+ if (eventType === "organization.created" && CLERK_USER_ID_PATTERN.test(actorId)) {
28504
+ await syncPermitUser({
28505
+ userId: actorId,
28506
+ email: void 0,
28507
+ displayName: void 0,
28508
+ eventType,
28509
+ eventAt: eventTimestamp,
28510
+ actorId
28511
+ });
28512
+ await Promise.all(
28513
+ workspaces2.flatMap((workspace) => {
28514
+ const assignments = [];
28515
+ if (workspace.workspaceKey) {
28516
+ assignments.push(
28517
+ upsertPermitWorkspaceMembershipRole({
28518
+ userId: actorId,
28519
+ tenantKey: organizationId,
28520
+ role: "tenant_admin",
28521
+ resourceInstance: `workspace:${workspace.workspaceKey}`
28522
+ })
28523
+ );
28524
+ }
28525
+ assignments.push(
28526
+ ...workspace.deploymentKeys.map(
28527
+ (deploymentKey) => upsertPermitDeploymentMembershipRole({
28528
+ userId: actorId,
28529
+ tenantKey: organizationId,
28530
+ role: "tenant_admin",
28531
+ resourceInstance: `deployment:${deploymentKey}`
28532
+ })
28533
+ )
28534
+ );
28535
+ return assignments;
28536
+ })
28537
+ );
28538
+ }
28024
28539
  const principal = await client.mutation(mcApi2.identity.upsertPrincipal, {
28025
28540
  principalId: organizationId,
28026
28541
  principalType: "group",
@@ -28071,6 +28586,8 @@ async function handleClerkWebhook(args) {
28071
28586
  acknowledged: true,
28072
28587
  eventType,
28073
28588
  tenantId: tenant.tenantId,
28589
+ provisioned: tenant.provisioned,
28590
+ workspaceCount: workspaces2.length,
28074
28591
  principalId: organizationId,
28075
28592
  principal,
28076
28593
  alias
@@ -28165,9 +28682,9 @@ async function handleClerkWebhook(args) {
28165
28682
  if (isMembershipEvent || isInvitationEvent) {
28166
28683
  const client = await getClient();
28167
28684
  const org = extractOrganizationIds(data);
28168
- const tenant = await resolveTenantByOrgSlug({
28685
+ const tenant = await resolveTenantByClerkOrganization({
28169
28686
  client,
28170
- organizationSlug: org.organizationSlug
28687
+ organizationId: org.organizationId
28171
28688
  });
28172
28689
  if (!tenant) {
28173
28690
  return webhookError(
@@ -28186,16 +28703,26 @@ async function handleClerkWebhook(args) {
28186
28703
  const userId = readString28(data.user_id) || readString28(asRecord26(data.public_user_data).user_id) || readString28(asRecord26(data.user).id);
28187
28704
  const rawRole = readString28(data.role);
28188
28705
  const role = normalizeRole(rawRole);
28189
- const permitTenantKey = tenant.tenantSlug;
28706
+ const permitTenantKey = tenantPermitKey({
28707
+ organizationId: org.organizationId
28708
+ });
28190
28709
  if (!permitTenantKey) {
28191
28710
  return webhookError(
28192
28711
  "INVALID_REQUEST",
28193
28712
  400,
28194
- "Clerk organization webhook payload missing organization tenant key.",
28713
+ "Clerk organization webhook payload missing canonical organization id.",
28195
28714
  args.correlationId,
28196
28715
  args.policyTraceId
28197
28716
  );
28198
28717
  }
28718
+ const workspaceProjections = await upsertPermitWorkspaceProjectionsForTenant({
28719
+ client,
28720
+ tenant,
28721
+ tenantKey: permitTenantKey,
28722
+ eventType,
28723
+ eventAt: eventTimestamp,
28724
+ actorId
28725
+ });
28199
28726
  if (INVITATION_EVENTS.has(eventType)) {
28200
28727
  const invitationId = readString28(data.id);
28201
28728
  const invitationAccepted = eventType === "organizationInvitation.accepted";
@@ -28258,6 +28785,32 @@ async function handleClerkWebhook(args) {
28258
28785
  tenantKey: permitTenantKey,
28259
28786
  role
28260
28787
  });
28788
+ await Promise.all(
28789
+ workspaceProjections.flatMap((workspace) => {
28790
+ const assignments = [];
28791
+ if (workspace.workspaceKey) {
28792
+ assignments.push(
28793
+ upsertPermitWorkspaceMembershipRole({
28794
+ userId,
28795
+ tenantKey: permitTenantKey,
28796
+ role,
28797
+ resourceInstance: `workspace:${workspace.workspaceKey}`
28798
+ })
28799
+ );
28800
+ }
28801
+ assignments.push(
28802
+ ...workspace.deploymentKeys.map(
28803
+ (deploymentKey) => upsertPermitDeploymentMembershipRole({
28804
+ userId,
28805
+ tenantKey: permitTenantKey,
28806
+ role,
28807
+ resourceInstance: `deployment:${deploymentKey}`
28808
+ })
28809
+ )
28810
+ );
28811
+ return assignments;
28812
+ })
28813
+ );
28261
28814
  await client.mutation(mcApi2.identity.upsertMembership, {
28262
28815
  principalId: userId,
28263
28816
  principalRefId: void 0,
@@ -28298,6 +28851,30 @@ async function handleClerkWebhook(args) {
28298
28851
  userId,
28299
28852
  tenantKey: permitTenantKey
28300
28853
  });
28854
+ await Promise.all(
28855
+ workspaceProjections.flatMap((workspace) => {
28856
+ const revocations = [];
28857
+ if (workspace.workspaceKey) {
28858
+ revocations.push(
28859
+ revokePermitWorkspaceMembershipRoles({
28860
+ userId,
28861
+ tenantKey: permitTenantKey,
28862
+ resourceInstance: `workspace:${workspace.workspaceKey}`
28863
+ })
28864
+ );
28865
+ }
28866
+ revocations.push(
28867
+ ...workspace.deploymentKeys.map(
28868
+ (deploymentKey) => revokePermitDeploymentMembershipRoles({
28869
+ userId,
28870
+ tenantKey: permitTenantKey,
28871
+ resourceInstance: `deployment:${deploymentKey}`
28872
+ })
28873
+ )
28874
+ );
28875
+ return revocations;
28876
+ })
28877
+ );
28301
28878
  const existing = await client.query(mcApi2.identity.getMembershipForPrincipal, {
28302
28879
  principalId: userId,
28303
28880
  tenantId: tenant.tenantId,
@@ -28395,6 +28972,30 @@ async function handleClerkWebhook(args) {
28395
28972
  userId,
28396
28973
  tenantKey: permitTenantKey
28397
28974
  });
28975
+ await Promise.all(
28976
+ workspaceProjections.flatMap((workspace) => {
28977
+ const revocations = [];
28978
+ if (workspace.workspaceKey) {
28979
+ revocations.push(
28980
+ revokePermitWorkspaceMembershipRoles({
28981
+ userId,
28982
+ tenantKey: permitTenantKey,
28983
+ resourceInstance: `workspace:${workspace.workspaceKey}`
28984
+ })
28985
+ );
28986
+ }
28987
+ revocations.push(
28988
+ ...workspace.deploymentKeys.map(
28989
+ (deploymentKey) => revokePermitDeploymentMembershipRoles({
28990
+ userId,
28991
+ tenantKey: permitTenantKey,
28992
+ resourceInstance: `deployment:${deploymentKey}`
28993
+ })
28994
+ )
28995
+ );
28996
+ return revocations;
28997
+ })
28998
+ );
28398
28999
  const existing = await client.query(mcApi2.identity.getMembershipForPrincipal, {
28399
29000
  principalId: userId,
28400
29001
  tenantId: tenant.tenantId,
@@ -28446,6 +29047,32 @@ async function handleClerkWebhook(args) {
28446
29047
  tenantKey: permitTenantKey,
28447
29048
  role
28448
29049
  });
29050
+ await Promise.all(
29051
+ workspaceProjections.flatMap((workspace) => {
29052
+ const assignments = [];
29053
+ if (workspace.workspaceKey) {
29054
+ assignments.push(
29055
+ upsertPermitWorkspaceMembershipRole({
29056
+ userId,
29057
+ tenantKey: permitTenantKey,
29058
+ role,
29059
+ resourceInstance: `workspace:${workspace.workspaceKey}`
29060
+ })
29061
+ );
29062
+ }
29063
+ assignments.push(
29064
+ ...workspace.deploymentKeys.map(
29065
+ (deploymentKey) => upsertPermitDeploymentMembershipRole({
29066
+ userId,
29067
+ tenantKey: permitTenantKey,
29068
+ role,
29069
+ resourceInstance: `deployment:${deploymentKey}`
29070
+ })
29071
+ )
29072
+ );
29073
+ return assignments;
29074
+ })
29075
+ );
28449
29076
  return successResponse(
28450
29077
  {
28451
29078
  acknowledged: true,