@lucern/graph-primitives 1.0.27 → 1.0.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/dist/beliefDecay.js.map +1 -1
  2. package/dist/beliefEvidenceLinks.js.map +1 -1
  3. package/dist/beliefEvidenceLinks.operational.js.map +1 -1
  4. package/dist/contradictions.js +3 -3
  5. package/dist/contradictions.js.map +1 -1
  6. package/dist/convex.js.map +1 -1
  7. package/dist/entityBridge.js.map +1 -1
  8. package/dist/entityLifecycle.js +7 -39
  9. package/dist/entityLifecycle.js.map +1 -1
  10. package/dist/epistemicAnswers.js.map +1 -1
  11. package/dist/epistemicBeliefs.admin.js +6 -42
  12. package/dist/epistemicBeliefs.admin.js.map +1 -1
  13. package/dist/epistemicBeliefs.backfills.js +2 -21
  14. package/dist/epistemicBeliefs.backfills.js.map +1 -1
  15. package/dist/epistemicBeliefs.confidence.d.ts +1 -0
  16. package/dist/epistemicBeliefs.confidence.js +4 -40
  17. package/dist/epistemicBeliefs.confidence.js.map +1 -1
  18. package/dist/epistemicBeliefs.core.js +6 -44
  19. package/dist/epistemicBeliefs.core.js.map +1 -1
  20. package/dist/epistemicBeliefs.d.ts +1 -0
  21. package/dist/epistemicBeliefs.forkEvidence.js +2 -22
  22. package/dist/epistemicBeliefs.forkEvidence.js.map +1 -1
  23. package/dist/epistemicBeliefs.helpers.d.ts +3 -27
  24. package/dist/epistemicBeliefs.helpers.js +4 -40
  25. package/dist/epistemicBeliefs.helpers.js.map +1 -1
  26. package/dist/epistemicBeliefs.internal.js +2 -22
  27. package/dist/epistemicBeliefs.internal.js.map +1 -1
  28. package/dist/epistemicBeliefs.js +17 -55
  29. package/dist/epistemicBeliefs.js.map +1 -1
  30. package/dist/epistemicBeliefs.lifecycle.js +7 -45
  31. package/dist/epistemicBeliefs.lifecycle.js.map +1 -1
  32. package/dist/epistemicBeliefs.links.js +7 -43
  33. package/dist/epistemicBeliefs.links.js.map +1 -1
  34. package/dist/epistemicBeliefs.queries.js.map +1 -1
  35. package/dist/epistemicBeliefs.topicAnchor.js.map +1 -1
  36. package/dist/epistemicContracts.evaluators.js +4 -40
  37. package/dist/epistemicContracts.evaluators.js.map +1 -1
  38. package/dist/epistemicContracts.handlers.js +4 -40
  39. package/dist/epistemicContracts.handlers.js.map +1 -1
  40. package/dist/epistemicContracts.js +4 -40
  41. package/dist/epistemicContracts.js.map +1 -1
  42. package/dist/epistemicEdgeCreation.js.map +1 -1
  43. package/dist/epistemicEdges.handlers.js.map +1 -1
  44. package/dist/epistemicEdges.js +4 -4
  45. package/dist/epistemicEdges.js.map +1 -1
  46. package/dist/epistemicEdges.mutations.js +4 -4
  47. package/dist/epistemicEdges.mutations.js.map +1 -1
  48. package/dist/epistemicEdges.queries.js.map +1 -1
  49. package/dist/epistemicEvidence.js +5 -5
  50. package/dist/epistemicEvidence.js.map +1 -1
  51. package/dist/epistemicEvidenceHelpers.js.map +1 -1
  52. package/dist/epistemicEvidenceMutations.js +5 -5
  53. package/dist/epistemicEvidenceMutations.js.map +1 -1
  54. package/dist/epistemicEvidenceQueries.js.map +1 -1
  55. package/dist/epistemicHelpers.js.map +1 -1
  56. package/dist/epistemicLinking.js.map +1 -1
  57. package/dist/epistemicNodeCreation.js.map +1 -1
  58. package/dist/epistemicNodes.internal.js.map +1 -1
  59. package/dist/epistemicNodes.js +4 -4
  60. package/dist/epistemicNodes.js.map +1 -1
  61. package/dist/epistemicNodes.mutations.js +4 -4
  62. package/dist/epistemicNodes.mutations.js.map +1 -1
  63. package/dist/epistemicNodes.queries.js.map +1 -1
  64. package/dist/epistemicQuestions.conviction.js.map +1 -1
  65. package/dist/epistemicQuestions.create.js.map +1 -1
  66. package/dist/epistemicQuestions.evidence.js.map +1 -1
  67. package/dist/epistemicQuestions.helpers.js.map +1 -1
  68. package/dist/epistemicQuestions.js.map +1 -1
  69. package/dist/epistemicQuestions.lifecycle.js.map +1 -1
  70. package/dist/epistemicQuestions.queries.js.map +1 -1
  71. package/dist/epistemicQuestions.sprint.js.map +1 -1
  72. package/dist/epistemicQuestions.tail.js.map +1 -1
  73. package/dist/epistemicSources.js +2 -2
  74. package/dist/epistemicSources.js.map +1 -1
  75. package/dist/helpers.js.map +1 -1
  76. package/dist/index.d.ts +1 -0
  77. package/dist/index.js +50 -121
  78. package/dist/index.js.map +1 -1
  79. package/dist/ontologyApproval.js.map +1 -1
  80. package/dist/ontologyDefinitions.js.map +1 -1
  81. package/dist/ontologyRegistry.js.map +1 -1
  82. package/dist/projectionReconciliation.js.map +1 -1
  83. package/dist/proof-attestation.json +1 -1
  84. package/dist/questionEvidenceLinks.js.map +1 -1
  85. package/dist/resolvers.js.map +1 -1
  86. package/dist/scopeResolverCompat.js.map +1 -1
  87. package/dist/topicProjectOverlay.js.map +1 -1
  88. package/dist/topicScope.js.map +1 -1
  89. package/dist/workflowBridge.js.map +1 -1
  90. package/dist/workspaceIsolation.js.map +1 -1
  91. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -1,10 +1,11 @@
1
1
  import { normalizeTupleContradictionPolicy, mkOpinion, createInheritedContractRecord, confidenceFromSL, getRescoringSchedule, conditionalDeduction, project, dampedDependencyCascade, hasProjectedOpinionChanged, detectTupleContradiction, evaluateTupleContradictionTransition, readOpinionFromRecord, trustDiscount, applyNegativeSupport, cumulativeFusion, applyNegativeEvidence, computeEffectiveDecay, computeDeadlineUrgency, computeBaseDecay, bayesianUpdate, DECAY_TIERS, DEADLINE_URGENCY, parseEvidentialEvaluatorConfig, compareMetricValue, buildEvidentialRationale, parseMetricCheckerConfig, getEvaluatorInputRecord, pickFiniteNumber, resolveComparisonResult, buildComparisonRationale, parseReferenceCheckCounterConfig, parseTemporalDeadlineConfig, parseMarketIndexComparatorConfig } from '@lucern/confidence';
2
- import { v, ConvexError } from 'convex/values';
3
- import { checkScopeAccess, getAccessibleProjectIds, checkProjectAccess, requireProjectAccess } from '@lucern/access-control/access';
2
+ import { v } from 'convex/values';
3
+ import { throwStructuredMutationError } from '@lucern/access-control/structuredMutationError';
4
4
  import { canAudienceClassAccess, normalizeAudienceKey, classFromAudienceKey } from '@lucern/access-control/audience';
5
5
  import { getCurrentUserId } from '@lucern/access-control/auth';
6
6
  import { componentsGeneric, anyApi, internalMutationGeneric, mutationGeneric, queryGeneric, internalQueryGeneric, internalActionGeneric } from 'convex/server';
7
7
  import { isNodeType, getLayerForNodeType } from '@lucern/contracts/schema-helpers/spine/tables/epistemicNodes';
8
+ import { requireScopeWriteAccess, checkScopeAccess, getAccessibleProjectIds, checkProjectAccess } from '@lucern/access-control/access';
8
9
  import { permissiveReturn } from '@lucern/contracts/schema-helpers/validators';
9
10
  import { assertSchemaEnumValue } from '@lucern/contracts/schema-helpers/enumValidation';
10
11
  import { generateGlobalId, assertUuidV7Identity, generateUuidV7, assertStorageEdgeVocabulary, assertUuidShapedEdgeEndpoint, isUuidV7 } from '@lucern/contracts/ids';
@@ -1745,26 +1746,6 @@ var DEFAULT_CONFIDENCE_POLICY = {
1745
1746
  scoringMode: "after_worktree",
1746
1747
  tupleContradiction: normalizeTupleContradictionPolicy()
1747
1748
  };
1748
- function throwStructuredMutationError(args) {
1749
- const data = {
1750
- structuredMutationError: true,
1751
- message: args.message,
1752
- status: args.status,
1753
- code: args.code,
1754
- invariantCode: args.invariantCode,
1755
- suggestion: args.suggestion,
1756
- details: args.details
1757
- };
1758
- const error = new ConvexError(
1759
- data
1760
- );
1761
- error.status = args.status;
1762
- error.code = args.code;
1763
- error.invariantCode = args.invariantCode;
1764
- error.suggestion = args.suggestion;
1765
- error.details = args.details;
1766
- throw error;
1767
- }
1768
1749
  function readFiniteNumber(value) {
1769
1750
  return typeof value === "number" && Number.isFinite(value) ? value : void 0;
1770
1751
  }
@@ -2098,23 +2079,6 @@ async function requireAuthenticatedUserId(ctx) {
2098
2079
  }
2099
2080
  return userId;
2100
2081
  }
2101
- async function requireProjectWriteAccess(ctx, projectId, userId) {
2102
- const hasAccess = await checkProjectAccess(
2103
- ctx,
2104
- projectId,
2105
- userId
2106
- );
2107
- if (!hasAccess) {
2108
- throwStructuredMutationError({
2109
- message: `Project write access denied for topic ${projectId}.`,
2110
- status: 403,
2111
- code: "PROJECT_ACCESS_DENIED",
2112
- invariantCode: "policy.scope_required",
2113
- suggestion: "The acting principal lacks project-write access to this topic. Request a topic grant (or, if the principal created this topic, run the creator-grant backfill) and retry.",
2114
- details: { topicId: projectId, principalId: userId }
2115
- });
2116
- }
2117
- }
2118
2082
  function resolveTraversalTargetNodeId(edge, direction) {
2119
2083
  const targetNodeId = direction === "outgoing" ? edge.toNodeId : edge.fromNodeId;
2120
2084
  return targetNodeId ?? void 0;
@@ -2275,7 +2239,7 @@ async function applyBeliefConfidenceChange(ctx, args) {
2275
2239
  details: { nodeId: args.nodeId }
2276
2240
  });
2277
2241
  }
2278
- await requireProjectWriteAccess(
2242
+ await requireScopeWriteAccess(
2279
2243
  ctx,
2280
2244
  node.projectId,
2281
2245
  args.authenticatedUserId
@@ -2839,8 +2803,6 @@ async function scheduleEmbeddingGeneration(args) {
2839
2803
  );
2840
2804
  }
2841
2805
  }
2842
-
2843
- // src/epistemicBeliefs.core.ts
2844
2806
  var create = mutation({
2845
2807
  args: {
2846
2808
  ...optionalBeliefScopeArgs,
@@ -2919,7 +2881,7 @@ var create = mutation({
2919
2881
  context: "epistemicBeliefs.create"
2920
2882
  });
2921
2883
  if (scope.projectId) {
2922
- await requireProjectWriteAccess(
2884
+ await requireScopeWriteAccess(
2923
2885
  ctx,
2924
2886
  scope.projectId,
2925
2887
  authenticatedUserId
@@ -3159,7 +3121,7 @@ var refineBelief = mutation({
3159
3121
  details: { nodeId: args.nodeId }
3160
3122
  });
3161
3123
  }
3162
- await requireProjectWriteAccess(ctx, node.projectId, authenticatedUserId);
3124
+ await requireScopeWriteAccess(ctx, node.projectId, authenticatedUserId);
3163
3125
  if (typeof node.confidence === "number" && Number.isFinite(node.confidence)) {
3164
3126
  throwStructuredMutationError({
3165
3127
  message: "Scored beliefs are immutable. Use forkBelief to evolve a scored belief.",
@@ -3379,7 +3341,7 @@ var forkBelief = mutation({
3379
3341
  details: { parentNodeId: args.parentNodeId }
3380
3342
  });
3381
3343
  }
3382
- await requireProjectWriteAccess(ctx, parent.projectId, authenticatedUserId);
3344
+ await requireScopeWriteAccess(ctx, parent.projectId, authenticatedUserId);
3383
3345
  const metadata = parent.metadata;
3384
3346
  const forkBeliefStatus = "hypothesis";
3385
3347
  const forkMode = args.forkMode ?? "supersede";
@@ -3677,7 +3639,7 @@ var updateStatus = mutation({
3677
3639
  if (!node.projectId) {
3678
3640
  throw new Error("Belief has no project scope");
3679
3641
  }
3680
- await requireProjectWriteAccess(ctx, node.projectId, authenticatedUserId);
3642
+ await requireScopeWriteAccess(ctx, node.projectId, authenticatedUserId);
3681
3643
  const previousStatus = node.status;
3682
3644
  const metadata = node.metadata || {};
3683
3645
  await ctx.db.patch(args.nodeId, {
@@ -3722,7 +3684,7 @@ var archive = mutation({
3722
3684
  if (!node.projectId) {
3723
3685
  throw new Error("Belief has no project scope");
3724
3686
  }
3725
- await requireProjectWriteAccess(ctx, node.projectId, authenticatedUserId);
3687
+ await requireScopeWriteAccess(ctx, node.projectId, authenticatedUserId);
3726
3688
  return await ctx.runMutation(
3727
3689
  // Use updateStatus internally
3728
3690
  internal.epistemicBeliefs.updateStatusInternal,
@@ -3752,7 +3714,7 @@ var updateRationale = mutation({
3752
3714
  if (!node.projectId) {
3753
3715
  throw new Error("Belief has no project scope");
3754
3716
  }
3755
- await requireProjectWriteAccess(ctx, node.projectId, authenticatedUserId);
3717
+ await requireScopeWriteAccess(ctx, node.projectId, authenticatedUserId);
3756
3718
  const metadata = node.metadata || {};
3757
3719
  const previousRationale = typeof metadata.rationale === "string" ? metadata.rationale : void 0;
3758
3720
  const nextRationale = args.rationale?.trim();
@@ -4015,7 +3977,7 @@ var updatePillar = mutation({
4015
3977
  if (!existingNode.projectId) {
4016
3978
  throw new Error("Belief has no project scope");
4017
3979
  }
4018
- await requireProjectWriteAccess(
3980
+ await requireScopeWriteAccess(
4019
3981
  ctx,
4020
3982
  existingNode.projectId,
4021
3983
  authenticatedUserId
@@ -4121,7 +4083,7 @@ var linkBeliefs = mutation({
4121
4083
  if (!fromNode.projectId) {
4122
4084
  throw new Error("Belief has no project scope");
4123
4085
  }
4124
- await requireProjectWriteAccess(
4086
+ await requireScopeWriteAccess(
4125
4087
  ctx,
4126
4088
  fromNode.projectId,
4127
4089
  authenticatedUserId
@@ -4177,7 +4139,7 @@ var linkEvidence = mutation({
4177
4139
  if (!belief.projectId) {
4178
4140
  throw new Error("Belief has no project scope");
4179
4141
  }
4180
- await requireProjectWriteAccess(ctx, belief.projectId, authenticatedUserId);
4142
+ await requireScopeWriteAccess(ctx, belief.projectId, authenticatedUserId);
4181
4143
  const insight = await ctx.db.get(args.insightId);
4182
4144
  if (!insight || insight.nodeType !== "evidence") {
4183
4145
  throw new Error("Insight not found");
@@ -4268,7 +4230,7 @@ var unlinkEvidence = mutation({
4268
4230
  if (!evidenceNode.projectId) {
4269
4231
  throw new Error("Evidence has no project scope");
4270
4232
  }
4271
- await requireProjectWriteAccess(
4233
+ await requireScopeWriteAccess(
4272
4234
  ctx,
4273
4235
  evidenceNode.projectId,
4274
4236
  authenticatedUserId
@@ -4449,7 +4411,7 @@ var deleteRelationship = mutation({
4449
4411
  if (!edge.projectId) {
4450
4412
  throw new Error("Edge has no project scope");
4451
4413
  }
4452
- await requireProjectWriteAccess(ctx, edge.projectId, authenticatedUserId);
4414
+ await requireScopeWriteAccess(ctx, edge.projectId, authenticatedUserId);
4453
4415
  const previousState = {
4454
4416
  fromNodeId: edge.fromNodeId,
4455
4417
  toNodeId: edge.toNodeId,
@@ -4496,7 +4458,7 @@ var updateCriticality = mutation({
4496
4458
  if (!node.projectId) {
4497
4459
  throw new Error("Belief has no project scope");
4498
4460
  }
4499
- await requireProjectWriteAccess(ctx, node.projectId, authenticatedUserId);
4461
+ await requireScopeWriteAccess(ctx, node.projectId, authenticatedUserId);
4500
4462
  const metadata = node.metadata || {};
4501
4463
  const previousCriticality = metadata.criticality;
4502
4464
  await ctx.db.patch(args.nodeId, {
@@ -4565,7 +4527,7 @@ var batchUpdateCriticality = mutation({
4565
4527
  results.push({ beliefId: update5.beliefId, success: false });
4566
4528
  continue;
4567
4529
  }
4568
- await requireProjectWriteAccess(
4530
+ await requireScopeWriteAccess(
4569
4531
  ctx,
4570
4532
  node.projectId,
4571
4533
  authenticatedUserId
@@ -7953,7 +7915,7 @@ var updateStatus2 = mutation({
7953
7915
  throw new Error("Contradiction not found");
7954
7916
  }
7955
7917
  if (existing.projectId && args.userId) {
7956
- await requireProjectAccess(ctx, existing.projectId, args.userId);
7918
+ await requireScopeWriteAccess(ctx, existing.projectId, args.userId);
7957
7919
  }
7958
7920
  const now = Date.now();
7959
7921
  const update5 = { status: args.status };
@@ -8004,7 +7966,7 @@ var resolve = mutation({
8004
7966
  throw new Error("Contradiction not found");
8005
7967
  }
8006
7968
  if (existing.projectId) {
8007
- await requireProjectAccess(ctx, existing.projectId, args.resolvedBy);
7969
+ await requireScopeWriteAccess(ctx, existing.projectId, args.resolvedBy);
8008
7970
  }
8009
7971
  const now = Date.now();
8010
7972
  await ctx.db.patch(args.contradictionId, {
@@ -8756,30 +8718,10 @@ async function validateEntityTypeForTopic(ctx, topicId, nodeType) {
8756
8718
  }
8757
8719
 
8758
8720
  // src/entityLifecycle.ts
8759
- function throwStructuredMutationError2(args) {
8760
- const data = {
8761
- structuredMutationError: true,
8762
- message: args.message,
8763
- status: args.status,
8764
- code: args.code,
8765
- invariantCode: args.invariantCode,
8766
- suggestion: args.suggestion,
8767
- details: args.details
8768
- };
8769
- const error = new ConvexError(
8770
- data
8771
- );
8772
- error.status = args.status;
8773
- error.code = args.code;
8774
- error.invariantCode = args.invariantCode;
8775
- error.suggestion = args.suggestion;
8776
- error.details = args.details;
8777
- throw error;
8778
- }
8779
8721
  async function requireAuthenticatedUserId3(ctx) {
8780
8722
  const userId = await getCurrentUserId(ctx);
8781
8723
  if (!userId) {
8782
- throwStructuredMutationError2({
8724
+ throwStructuredMutationError({
8783
8725
  message: "Authentication required.",
8784
8726
  status: 401,
8785
8727
  code: "AUTHENTICATION_REQUIRED",
@@ -8789,19 +8731,6 @@ async function requireAuthenticatedUserId3(ctx) {
8789
8731
  }
8790
8732
  return userId;
8791
8733
  }
8792
- async function requireProjectWriteAccess3(ctx, projectId, userId) {
8793
- const hasAccess = await checkProjectAccess(ctx, projectId, userId);
8794
- if (!hasAccess) {
8795
- throwStructuredMutationError2({
8796
- message: `Project write access denied for topic ${projectId}.`,
8797
- status: 403,
8798
- code: "PROJECT_ACCESS_DENIED",
8799
- invariantCode: "policy.scope_required",
8800
- suggestion: "The acting principal lacks project-write access to this topic. Request a topic grant (or, if the principal created this topic, run the creator-grant backfill) and retry.",
8801
- details: { topicId: projectId, principalId: userId }
8802
- });
8803
- }
8804
- }
8805
8734
  function generateContentHash3(nodeType, text) {
8806
8735
  const content = `${nodeType}:${text.trim().toLowerCase().replace(/\s+/g, " ")}`;
8807
8736
  let hash = 5381;
@@ -8928,7 +8857,7 @@ var createEntity = mutation({
8928
8857
  const now = Date.now();
8929
8858
  const canonicalText = args.canonicalText.trim();
8930
8859
  if (!canonicalText) {
8931
- throwStructuredMutationError2({
8860
+ throwStructuredMutationError({
8932
8861
  message: "canonicalText is required.",
8933
8862
  status: 400,
8934
8863
  code: "INVALID_REQUEST",
@@ -8936,7 +8865,7 @@ var createEntity = mutation({
8936
8865
  });
8937
8866
  }
8938
8867
  if (!isOntologicalNodeType(args.nodeType)) {
8939
- throwStructuredMutationError2({
8868
+ throwStructuredMutationError({
8940
8869
  message: `"${args.nodeType}" is not an ontological entity type. Use epistemicBeliefs.create for epistemic nodes.`,
8941
8870
  status: 400,
8942
8871
  code: "INVALID_NODE_TYPE",
@@ -8949,7 +8878,7 @@ var createEntity = mutation({
8949
8878
  projectId: args.projectId
8950
8879
  });
8951
8880
  if (scope.projectId) {
8952
- await requireProjectWriteAccess3(
8881
+ await requireScopeWriteAccess(
8953
8882
  ctx,
8954
8883
  scope.projectId,
8955
8884
  authenticatedUserId
@@ -8962,7 +8891,7 @@ var createEntity = mutation({
8962
8891
  args.nodeType
8963
8892
  );
8964
8893
  if (!ontologyValidation.valid) {
8965
- throwStructuredMutationError2({
8894
+ throwStructuredMutationError({
8966
8895
  message: `Ontology validation failed: ${ontologyValidation.error}`,
8967
8896
  status: 400,
8968
8897
  code: "ONTOLOGY_VALIDATION_ERROR",
@@ -8980,7 +8909,7 @@ var createEntity = mutation({
8980
8909
  scope.tenantId
8981
8910
  );
8982
8911
  if (!validation.valid) {
8983
- throwStructuredMutationError2({
8912
+ throwStructuredMutationError({
8984
8913
  message: `Entity metadata validation failed: ${validation.errors.join("; ")}`,
8985
8914
  status: 400,
8986
8915
  code: "VALIDATION_ERROR",
@@ -9074,7 +9003,7 @@ var updateEntityAttributes = mutation({
9074
9003
  const now = Date.now();
9075
9004
  const node = await ctx.db.get(args.nodeId);
9076
9005
  if (!node) {
9077
- throwStructuredMutationError2({
9006
+ throwStructuredMutationError({
9078
9007
  message: "Entity not found.",
9079
9008
  status: 404,
9080
9009
  code: "NOT_FOUND",
@@ -9082,7 +9011,7 @@ var updateEntityAttributes = mutation({
9082
9011
  });
9083
9012
  }
9084
9013
  if (!isOntologicalNodeType(node.nodeType)) {
9085
- throwStructuredMutationError2({
9014
+ throwStructuredMutationError({
9086
9015
  message: `Node "${args.nodeId}" is a ${node.nodeType}, not an entity. Use belief/question APIs for epistemic nodes.`,
9087
9016
  status: 400,
9088
9017
  code: "LIFECYCLE_VIOLATION",
@@ -9092,7 +9021,7 @@ var updateEntityAttributes = mutation({
9092
9021
  }
9093
9022
  const scopeProjectId = typeof node.projectId === "string" && node.projectId.trim().length > 0 ? node.projectId : void 0;
9094
9023
  if (scopeProjectId) {
9095
- await requireProjectWriteAccess3(ctx, scopeProjectId, authenticatedUserId);
9024
+ await requireScopeWriteAccess(ctx, scopeProjectId, authenticatedUserId);
9096
9025
  }
9097
9026
  const existingMetadata = node.metadata || {};
9098
9027
  const newMetadataFields = args.metadata !== void 0 ? args.metadata || {} : {};
@@ -9101,7 +9030,7 @@ var updateEntityAttributes = mutation({
9101
9030
  mergedMetadata.subtype = args.subtype;
9102
9031
  }
9103
9032
  if (args.canonicalText !== void 0 && args.canonicalText.trim().length === 0) {
9104
- throwStructuredMutationError2({
9033
+ throwStructuredMutationError({
9105
9034
  message: "canonicalText cannot be empty.",
9106
9035
  status: 400,
9107
9036
  code: "INVALID_REQUEST",
@@ -9116,7 +9045,7 @@ var updateEntityAttributes = mutation({
9116
9045
  tenantId: typeof node.tenantId === "string" ? node.tenantId : void 0
9117
9046
  });
9118
9047
  if (duplicate && String(duplicate._id) !== String(args.nodeId)) {
9119
- throwStructuredMutationError2({
9048
+ throwStructuredMutationError({
9120
9049
  message: "A canonical entity with this name already exists in the tenant scope.",
9121
9050
  status: 409,
9122
9051
  code: "CONFLICT",
@@ -9137,7 +9066,7 @@ var updateEntityAttributes = mutation({
9137
9066
  typeof node.tenantId === "string" ? node.tenantId : void 0
9138
9067
  );
9139
9068
  if (!validation.valid) {
9140
- throwStructuredMutationError2({
9069
+ throwStructuredMutationError({
9141
9070
  message: `Entity metadata validation failed: ${validation.errors.join("; ")}`,
9142
9071
  status: 400,
9143
9072
  code: "VALIDATION_ERROR",
@@ -9211,7 +9140,7 @@ var mergeEntities = mutation({
9211
9140
  const canonical = await ctx.db.get(args.canonicalNodeId);
9212
9141
  const duplicate = await ctx.db.get(args.duplicateNodeId);
9213
9142
  if (!canonical || !duplicate) {
9214
- throwStructuredMutationError2({
9143
+ throwStructuredMutationError({
9215
9144
  message: "One or both entity nodes not found.",
9216
9145
  status: 404,
9217
9146
  code: "NOT_FOUND",
@@ -9222,7 +9151,7 @@ var mergeEntities = mutation({
9222
9151
  });
9223
9152
  }
9224
9153
  if (!isOntologicalNodeType(canonical.nodeType) || !isOntologicalNodeType(duplicate.nodeType)) {
9225
- throwStructuredMutationError2({
9154
+ throwStructuredMutationError({
9226
9155
  message: "Both nodes must be ontological entities to merge.",
9227
9156
  status: 400,
9228
9157
  code: "LIFECYCLE_VIOLATION",
@@ -9230,7 +9159,7 @@ var mergeEntities = mutation({
9230
9159
  });
9231
9160
  }
9232
9161
  if (args.canonicalNodeId === args.duplicateNodeId) {
9233
- throwStructuredMutationError2({
9162
+ throwStructuredMutationError({
9234
9163
  message: "Cannot merge an entity with itself.",
9235
9164
  status: 400,
9236
9165
  code: "SELF_MERGE",
@@ -9240,14 +9169,14 @@ var mergeEntities = mutation({
9240
9169
  });
9241
9170
  }
9242
9171
  if (canonical.nodeType !== duplicate.nodeType) {
9243
- throwStructuredMutationError2({
9172
+ throwStructuredMutationError({
9244
9173
  message: `Cannot merge different entity types: ${canonical.nodeType} vs ${duplicate.nodeType}.`,
9245
9174
  status: 400,
9246
9175
  code: "TYPE_MISMATCH"
9247
9176
  });
9248
9177
  }
9249
9178
  if (canonical.projectId) {
9250
- await requireProjectWriteAccess3(
9179
+ await requireScopeWriteAccess(
9251
9180
  ctx,
9252
9181
  canonical.projectId,
9253
9182
  authenticatedUserId
@@ -9363,7 +9292,7 @@ var archiveEntity = mutation({
9363
9292
  const now = Date.now();
9364
9293
  const node = await ctx.db.get(args.nodeId);
9365
9294
  if (!node) {
9366
- throwStructuredMutationError2({
9295
+ throwStructuredMutationError({
9367
9296
  message: "Entity not found.",
9368
9297
  status: 404,
9369
9298
  code: "NOT_FOUND",
@@ -9371,7 +9300,7 @@ var archiveEntity = mutation({
9371
9300
  });
9372
9301
  }
9373
9302
  if (!isOntologicalNodeType(node.nodeType)) {
9374
- throwStructuredMutationError2({
9303
+ throwStructuredMutationError({
9375
9304
  message: `Node "${args.nodeId}" is a ${node.nodeType}, not an entity. Use belief archive APIs for epistemic nodes.`,
9376
9305
  status: 400,
9377
9306
  code: "LIFECYCLE_VIOLATION",
@@ -9379,7 +9308,7 @@ var archiveEntity = mutation({
9379
9308
  });
9380
9309
  }
9381
9310
  if (node.projectId) {
9382
- await requireProjectWriteAccess3(
9311
+ await requireScopeWriteAccess(
9383
9312
  ctx,
9384
9313
  node.projectId,
9385
9314
  authenticatedUserId
@@ -11670,7 +11599,7 @@ var create5 = mutation({
11670
11599
  }) : void 0;
11671
11600
  const resolvedProjectId = resolvedScope?.projectId ?? args.projectId;
11672
11601
  if (resolvedProjectId) {
11673
- await requireProjectAccess(ctx, resolvedProjectId, args.createdBy);
11602
+ await requireScopeWriteAccess(ctx, resolvedProjectId, args.createdBy);
11674
11603
  }
11675
11604
  const fromLayer = fromNode.epistemicLayer || getNodeLayer(fromNode.nodeType);
11676
11605
  const toLayer = toNode.epistemicLayer || getNodeLayer(toNode.nodeType);
@@ -11772,7 +11701,7 @@ var update2 = mutation({
11772
11701
  throw new Error("Edge not found");
11773
11702
  }
11774
11703
  if (edge.projectId && userId) {
11775
- await requireProjectAccess(ctx, edge.projectId, userId);
11704
+ await requireScopeWriteAccess(ctx, edge.projectId, userId);
11776
11705
  }
11777
11706
  const cleanUpdates = {};
11778
11707
  for (const [key, value] of Object.entries(updates)) {
@@ -11813,7 +11742,7 @@ var remove2 = mutation({
11813
11742
  return buildEdgeNotFoundResult();
11814
11743
  }
11815
11744
  if (edge.projectId && args.userId) {
11816
- await requireProjectAccess(ctx, edge.projectId, args.userId);
11745
+ await requireScopeWriteAccess(ctx, edge.projectId, args.userId);
11817
11746
  }
11818
11747
  if (edge.projectId) {
11819
11748
  await ctx.db.insert("epistemicAudit", {
@@ -12548,7 +12477,7 @@ var create6 = mutation({
12548
12477
  mutationName: "epistemicEvidence.create"
12549
12478
  });
12550
12479
  if (scope.projectId) {
12551
- await requireProjectAccess(ctx, scope.projectId, args.userId);
12480
+ await requireScopeWriteAccess(ctx, scope.projectId, args.userId);
12552
12481
  }
12553
12482
  const now = Date.now();
12554
12483
  const globalId = generateGlobalId();
@@ -12718,7 +12647,7 @@ var createAndLink = mutation({
12718
12647
  if (!scope) {
12719
12648
  throw new Error("Invalid scope: projectId or topicId is required");
12720
12649
  }
12721
- await requireProjectAccess(ctx, String(scope.topicId), args.userId);
12650
+ await requireScopeWriteAccess(ctx, String(scope.topicId), args.userId);
12722
12651
  const now = Date.now();
12723
12652
  const globalId = generateGlobalId();
12724
12653
  const contentHash = generateContentHash5(args.text);
@@ -13054,7 +12983,7 @@ var update3 = mutation({
13054
12983
  if (!node.projectId) {
13055
12984
  throw new Error("Evidence has no project scope");
13056
12985
  }
13057
- await checkProjectAccess(ctx, node.projectId, args.userId);
12986
+ await requireScopeWriteAccess(ctx, node.projectId, args.userId);
13058
12987
  const now = Date.now();
13059
12988
  const existingMeta = node.metadata || {};
13060
12989
  const metaUpdates = { ...existingMeta };
@@ -13121,7 +13050,7 @@ var flagAsIncorrect = mutation({
13121
13050
  if (!node.projectId) {
13122
13051
  throw new Error("Evidence has no project scope");
13123
13052
  }
13124
- await checkProjectAccess(ctx, node.projectId, args.userId);
13053
+ await requireScopeWriteAccess(ctx, node.projectId, args.userId);
13125
13054
  const existingMeta = node.metadata || {};
13126
13055
  await ctx.db.patch(node._id, {
13127
13056
  verificationStatus: "contradicted",
@@ -14596,7 +14525,7 @@ var update4 = mutation({
14596
14525
  throw new Error("Node not found");
14597
14526
  }
14598
14527
  if (node.projectId && userId) {
14599
- await requireProjectAccess(ctx, node.projectId, userId);
14528
+ await requireScopeWriteAccess(ctx, node.projectId, userId);
14600
14529
  }
14601
14530
  const cleanUpdates = {};
14602
14531
  for (const [key, value] of Object.entries(updates)) {
@@ -14657,7 +14586,7 @@ var supersede = mutation({
14657
14586
  throw new Error("Node not found");
14658
14587
  }
14659
14588
  if (oldNode.projectId) {
14660
- await requireProjectAccess(ctx, oldNode.projectId, args.createdBy);
14589
+ await requireScopeWriteAccess(ctx, oldNode.projectId, args.createdBy);
14661
14590
  }
14662
14591
  assertBeliefNodeSupersedeAllowed({
14663
14592
  node: oldNode,
@@ -14733,7 +14662,7 @@ var archive2 = mutation({
14733
14662
  throw new Error("Node not found");
14734
14663
  }
14735
14664
  if (node.projectId && args.userId) {
14736
- await requireProjectAccess(ctx, node.projectId, args.userId);
14665
+ await requireScopeWriteAccess(ctx, node.projectId, args.userId);
14737
14666
  }
14738
14667
  assertBeliefNodeArchiveAllowed({
14739
14668
  node,
@@ -18374,7 +18303,7 @@ var upsertSource = mutation({
18374
18303
  mutationName: "epistemicSources.upsertSource"
18375
18304
  });
18376
18305
  if (scope.projectId) {
18377
- await requireProjectAccess(ctx, scope.projectId, args.userId);
18306
+ await requireScopeWriteAccess(ctx, scope.projectId, args.userId);
18378
18307
  }
18379
18308
  const globalId = generateGlobalId();
18380
18309
  const title = normalizeString(args.title);