@lucern/mcp 0.3.0-alpha.12 → 0.3.0-alpha.14

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.
@@ -313,6 +313,7 @@ __export(src_exports, {
313
313
  LUCERN_SDK_VERSION: () => LUCERN_SDK_VERSION,
314
314
  LucernAccessControlError: () => LucernAccessControlError,
315
315
  LucernApiError: () => LucernApiError,
316
+ LucernControlPlaneIdentityError: () => LucernControlPlaneIdentityError,
316
317
  LucernSdkAuthContextError: () => LucernSdkAuthContextError,
317
318
  MANAGE_WRITE_POLICY: () => MANAGE_WRITE_POLICY,
318
319
  MATCH_ENTITY_TYPE: () => MATCH_ENTITY_TYPE,
@@ -344,6 +345,7 @@ __export(src_exports, {
344
345
  REMOVE_EDGES_BETWEEN: () => REMOVE_EDGES_BETWEEN,
345
346
  REMOVE_LENS_FROM_TOPIC: () => REMOVE_LENS_FROM_TOPIC,
346
347
  RESOLVE_EFFECTIVE_ONTOLOGY: () => RESOLVE_EFFECTIVE_ONTOLOGY,
348
+ RESOLVE_INTERACTIVE_PRINCIPAL: () => RESOLVE_INTERACTIVE_PRINCIPAL,
347
349
  RUN_GRAPH_INTELLIGENCE_QUERY: () => RUN_GRAPH_INTELLIGENCE_QUERY,
348
350
  SEARCH_BELIEFS: () => SEARCH_BELIEFS,
349
351
  SEARCH_EVIDENCE: () => SEARCH_EVIDENCE,
@@ -409,6 +411,8 @@ __export(src_exports, {
409
411
  createCanonicalAuthHeaders: () => createCanonicalAuthHeaders,
410
412
  createContextClient: () => createContextClient,
411
413
  createContextFacade: () => createContextFacade,
414
+ createControlPlaneClient: () => createControlPlaneClient,
415
+ createControlPlaneIdentityClient: () => createControlPlaneIdentityClient,
412
416
  createDecisionsClient: () => createDecisionsClient,
413
417
  createEmbeddingsClient: () => createEmbeddingsClient,
414
418
  createEventId: () => createEventId,
@@ -482,6 +486,7 @@ __export(src_exports, {
482
486
  normalizeDelegationChain: () => normalizeDelegationChain,
483
487
  normalizeNodeVerificationStatus: () => normalizeNodeVerificationStatus,
484
488
  normalizeNodeWriteInput: () => normalizeNodeWriteInput,
489
+ normalizeResolvedInteractivePrincipal: () => normalizeResolvedInteractivePrincipal,
485
490
  normalizeRetentionDays: () => normalizeRetentionDays,
486
491
  normalizeTopicQuery: () => normalizeTopicQuery,
487
492
  normalizeWebhookPatterns: () => normalizeWebhookPatterns,
@@ -571,14 +576,14 @@ function requireString(value, reason, label) {
571
576
  }
572
577
  return normalized;
573
578
  }
574
- function requirePrincipalType(principalType) {
575
- if (!principalType) {
579
+ function requirePrincipalType(principalType2) {
580
+ if (!principalType2) {
576
581
  throw new LucernSdkAuthContextError(
577
582
  "principal_missing",
578
583
  "Canonical Lucern SDK auth context is missing principalType."
579
584
  );
580
585
  }
581
- return principalType;
586
+ return principalType2;
582
587
  }
583
588
  function requireAuthMode(authMode) {
584
589
  if (!authMode) {
@@ -624,7 +629,7 @@ function normalizeCanonicalLucernAuthContext(input) {
624
629
  );
625
630
  const roles = cleanStringList(input.roles);
626
631
  const scopes = cleanStringList(input.scopes);
627
- const principalType = requirePrincipalType(input.principalType);
632
+ const principalType2 = requirePrincipalType(input.principalType);
628
633
  const authMode = requireAuthMode(input.authMode);
629
634
  const roleBasedInteractiveAuth = authMode === "interactive_user" && roles.length > 0;
630
635
  if (roles.length === 0 || scopes.length === 0 && !roleBasedInteractiveAuth) {
@@ -653,7 +658,7 @@ function normalizeCanonicalLucernAuthContext(input) {
653
658
  principalId,
654
659
  tenantId,
655
660
  workspaceId,
656
- principalType,
661
+ principalType: principalType2,
657
662
  authMode,
658
663
  roles,
659
664
  scopes,
@@ -1642,6 +1647,128 @@ function listResultFromEnvelope(data, legacyKey) {
1642
1647
  );
1643
1648
  }
1644
1649
 
1650
+ // ../sdk/src/control-plane.ts
1651
+ var LucernControlPlaneIdentityError = class extends Error {
1652
+ reason;
1653
+ principalStatus;
1654
+ tenantStatus;
1655
+ workspaceStatus;
1656
+ details;
1657
+ constructor(failure) {
1658
+ super(failure.message);
1659
+ this.name = "LucernControlPlaneIdentityError";
1660
+ this.reason = failure.reason;
1661
+ this.principalStatus = failure.principalStatus;
1662
+ this.tenantStatus = failure.tenantStatus;
1663
+ this.workspaceStatus = failure.workspaceStatus;
1664
+ this.details = failure.details;
1665
+ }
1666
+ };
1667
+ function cleanString3(value) {
1668
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
1669
+ }
1670
+ function stringList(value) {
1671
+ if (!Array.isArray(value)) {
1672
+ return [];
1673
+ }
1674
+ return [
1675
+ ...new Set(
1676
+ value.filter((entry) => typeof entry === "string").map((entry) => entry.trim()).filter(Boolean)
1677
+ )
1678
+ ];
1679
+ }
1680
+ function principalType(value) {
1681
+ switch (value) {
1682
+ case "service":
1683
+ case "service_principal":
1684
+ return "service";
1685
+ case "agent":
1686
+ return "agent";
1687
+ case "group":
1688
+ return "group";
1689
+ case "external_viewer":
1690
+ case "external_stakeholder":
1691
+ return "external_viewer";
1692
+ default:
1693
+ return "human";
1694
+ }
1695
+ }
1696
+ function adminFlags(roles) {
1697
+ const normalized = roles.map((role) => role.toLowerCase());
1698
+ const isPlatformAdmin = normalized.includes("platform_admin");
1699
+ const isTenantAdmin = isPlatformAdmin || normalized.includes("tenant_admin");
1700
+ const isWorkspaceAdmin = isTenantAdmin || normalized.includes("workspace_admin") || normalized.includes("workspace_owner");
1701
+ return { isPlatformAdmin, isTenantAdmin, isWorkspaceAdmin };
1702
+ }
1703
+ function normalizeResolvedInteractivePrincipal(payload) {
1704
+ if ("ok" in payload && payload.ok === false) {
1705
+ throw new LucernControlPlaneIdentityError(payload);
1706
+ }
1707
+ const principalId = cleanString3(payload.principalId);
1708
+ const clerkId = cleanString3(payload.clerkId);
1709
+ const tenantId = cleanString3(payload.tenantId);
1710
+ if (!principalId || !clerkId || !tenantId) {
1711
+ throw new LucernControlPlaneIdentityError({
1712
+ ok: false,
1713
+ reason: "resolver_unavailable",
1714
+ message: "Control-plane principal resolver returned an incomplete principal context.",
1715
+ principalStatus: payload.principalStatus ?? "missing",
1716
+ tenantStatus: payload.tenantStatus,
1717
+ workspaceStatus: payload.workspaceStatus
1718
+ });
1719
+ }
1720
+ const roles = stringList(payload.roles);
1721
+ const scopes = stringList(payload.scopes);
1722
+ const workspaceId = cleanString3(payload.workspaceId) ?? null;
1723
+ const flags = adminFlags(roles);
1724
+ return {
1725
+ principalId,
1726
+ principalType: principalType(payload.principalType),
1727
+ clerkId,
1728
+ tenantId,
1729
+ workspaceId,
1730
+ roles,
1731
+ scopes,
1732
+ groupIds: stringList(payload.groupIds),
1733
+ permittedToolNames: stringList(payload.permittedToolNames),
1734
+ permittedPackKeys: stringList(payload.permittedPackKeys),
1735
+ principalStatus: cleanString3(payload.principalStatus) ?? "active",
1736
+ tenantStatus: cleanString3(payload.tenantStatus) ?? "active",
1737
+ workspaceStatus: cleanString3(payload.workspaceStatus) ?? (workspaceId ? "active" : "none"),
1738
+ isPlatformAdmin: typeof payload.isPlatformAdmin === "boolean" ? payload.isPlatformAdmin : flags.isPlatformAdmin,
1739
+ isTenantAdmin: typeof payload.isTenantAdmin === "boolean" ? payload.isTenantAdmin : flags.isTenantAdmin,
1740
+ isWorkspaceAdmin: typeof payload.isWorkspaceAdmin === "boolean" ? payload.isWorkspaceAdmin : flags.isWorkspaceAdmin,
1741
+ permit: {
1742
+ subject: cleanString3(payload.permit?.subject) ?? principalId,
1743
+ tenant: cleanString3(payload.permit?.tenant) ?? tenantId,
1744
+ ...workspaceId ? { workspace: cleanString3(payload.permit?.workspace) ?? workspaceId } : {}
1745
+ },
1746
+ authMode: "interactive_user",
1747
+ sessionId: payload.sessionId,
1748
+ delegatedBy: payload.delegatedBy,
1749
+ expiresAt: payload.expiresAt
1750
+ };
1751
+ }
1752
+ function createControlPlaneIdentityClient(config = {}) {
1753
+ const gateway = createGatewayRequestClient(config);
1754
+ return {
1755
+ async resolveInteractivePrincipal(input) {
1756
+ return gateway.request({
1757
+ path: "/api/platform/v1/control-plane/identity/resolve-interactive-principal",
1758
+ method: "POST",
1759
+ body: input
1760
+ }).then(
1761
+ (response) => mapGatewayData(response, normalizeResolvedInteractivePrincipal)
1762
+ );
1763
+ }
1764
+ };
1765
+ }
1766
+ function createControlPlaneClient(config = {}) {
1767
+ return {
1768
+ identity: createControlPlaneIdentityClient(config)
1769
+ };
1770
+ }
1771
+
1645
1772
  // ../sdk/src/identityClient.ts
1646
1773
  function createIdentityWhoamiClient(config = {}) {
1647
1774
  const gateway = createGatewayRequestClient(config);
@@ -1709,13 +1836,25 @@ function createIdentityClient(config = {}) {
1709
1836
  (response) => mapGatewayData(response, (data) => ({
1710
1837
  principalId: data.principalId,
1711
1838
  principalType: data.principalType,
1839
+ clerkId: data.clerkId,
1712
1840
  tenantId: data.tenantId ?? null,
1713
1841
  workspaceId: data.workspaceId ?? null,
1714
1842
  scopes: Array.isArray(data.scopes) ? data.scopes : [],
1715
1843
  roles: Array.isArray(data.roles) ? data.roles : [],
1844
+ groupIds: Array.isArray(data.groupIds) ? data.groupIds : [],
1845
+ permittedToolNames: Array.isArray(data.permittedToolNames) ? data.permittedToolNames : [],
1846
+ permittedPackKeys: Array.isArray(data.permittedPackKeys) ? data.permittedPackKeys : [],
1847
+ principalStatus: data.principalStatus,
1848
+ tenantStatus: data.tenantStatus,
1849
+ workspaceStatus: data.workspaceStatus,
1716
1850
  isPlatformAdmin: data.isPlatformAdmin === true,
1717
1851
  isTenantAdmin: data.isTenantAdmin === true,
1718
1852
  isWorkspaceAdmin: data.isWorkspaceAdmin === true,
1853
+ permit: data.permit ?? (data.tenantId ? {
1854
+ subject: data.principalId,
1855
+ tenant: data.tenantId,
1856
+ ...data.workspaceId ? { workspace: data.workspaceId } : {}
1857
+ } : void 0),
1719
1858
  authMode: data.authMode,
1720
1859
  sessionId: data.sessionId,
1721
1860
  delegatedBy: data.delegatedBy,
@@ -1723,6 +1862,19 @@ function createIdentityClient(config = {}) {
1723
1862
  }))
1724
1863
  );
1725
1864
  },
1865
+ /**
1866
+ * Resolve a Clerk subject through the tenant control-plane Permit projection.
1867
+ * @deprecated Prefer lucern.controlPlane.identity.resolveInteractivePrincipal().
1868
+ */
1869
+ async resolveInteractivePrincipal(input) {
1870
+ return gateway.request({
1871
+ path: "/api/platform/v1/control-plane/identity/resolve-interactive-principal",
1872
+ method: "POST",
1873
+ body: input
1874
+ }).then(
1875
+ (response) => mapGatewayData(response, normalizeResolvedInteractivePrincipal)
1876
+ );
1877
+ },
1726
1878
  /**
1727
1879
  * List principals in the current identity scope.
1728
1880
  */
@@ -1919,7 +2071,7 @@ var LucernAccessControlError = class extends LucernSdkAuthContextError {
1919
2071
  this.policyDecision = policyDecision;
1920
2072
  }
1921
2073
  };
1922
- function cleanString3(value) {
2074
+ function cleanString4(value) {
1923
2075
  const normalized = value?.trim();
1924
2076
  return normalized ? normalized : void 0;
1925
2077
  }
@@ -1934,7 +2086,7 @@ function cleanStringList2(values) {
1934
2086
  ];
1935
2087
  }
1936
2088
  function requireString2(value, reason, label) {
1937
- const normalized = cleanString3(value);
2089
+ const normalized = cleanString4(value);
1938
2090
  if (!normalized) {
1939
2091
  throw new LucernAccessControlError(
1940
2092
  reason,
@@ -1943,13 +2095,19 @@ function requireString2(value, reason, label) {
1943
2095
  }
1944
2096
  return normalized;
1945
2097
  }
1946
- function normalizePrincipalType(principalType) {
1947
- if (principalType === "agent") {
2098
+ function normalizePrincipalType(principalType2) {
2099
+ if (principalType2 === "agent") {
1948
2100
  return "agent";
1949
2101
  }
1950
- if (principalType === "service") {
2102
+ if (principalType2 === "service") {
1951
2103
  return "service";
1952
2104
  }
2105
+ if (principalType2 === "group") {
2106
+ return "group";
2107
+ }
2108
+ if (principalType2 === "external_viewer") {
2109
+ return "external_viewer";
2110
+ }
1953
2111
  return "human";
1954
2112
  }
1955
2113
  function aliasKey(alias) {
@@ -1958,15 +2116,15 @@ function aliasKey(alias) {
1958
2116
  function normalizeAliases(input, canonicalClerkUserId) {
1959
2117
  const aliases = /* @__PURE__ */ new Map();
1960
2118
  for (const alias of input ?? []) {
1961
- const externalSubjectId = cleanString3(alias.externalSubjectId);
2119
+ const externalSubjectId = cleanString4(alias.externalSubjectId);
1962
2120
  if (!externalSubjectId) {
1963
2121
  continue;
1964
2122
  }
1965
2123
  const normalized = {
1966
- provider: cleanString3(alias.provider) ?? "clerk",
1967
- providerProjectId: cleanString3(alias.providerProjectId),
2124
+ provider: cleanString4(alias.provider) ?? "clerk",
2125
+ providerProjectId: cleanString4(alias.providerProjectId),
1968
2126
  externalSubjectId,
1969
- status: cleanString3(alias.status)
2127
+ status: cleanString4(alias.status)
1970
2128
  };
1971
2129
  aliases.set(aliasKey(normalized), normalized);
1972
2130
  }
@@ -2011,10 +2169,10 @@ function normalizeCanonicalPrincipalIdentity(input, options = {}) {
2011
2169
  "principal_missing",
2012
2170
  "principalId"
2013
2171
  );
2014
- const principalType = normalizePrincipalType(principalInput.principalType);
2015
- const observedClerkId = cleanString3(options.observedClerkId);
2016
- const canonicalClerkUserId = cleanString3(principalInput.canonicalClerkUserId) ?? cleanString3(principalInput.clerkId);
2017
- if (principalType === "human" && !canonicalClerkUserId) {
2172
+ const principalType2 = normalizePrincipalType(principalInput.principalType);
2173
+ const observedClerkId = cleanString4(options.observedClerkId);
2174
+ const canonicalClerkUserId = cleanString4(principalInput.canonicalClerkUserId) ?? cleanString4(principalInput.clerkId);
2175
+ if (principalType2 === "human" && !canonicalClerkUserId) {
2018
2176
  throw new LucernAccessControlError(
2019
2177
  "clerk_alias_missing",
2020
2178
  "Human principals require one canonical Clerk user id."
@@ -2036,11 +2194,11 @@ function normalizeCanonicalPrincipalIdentity(input, options = {}) {
2036
2194
  }
2037
2195
  return {
2038
2196
  principalId,
2039
- principalType,
2197
+ principalType: principalType2,
2040
2198
  canonicalClerkUserId,
2041
2199
  clerkIdentityAliases: aliases,
2042
- tenantId: cleanString3(principalInput.tenantId),
2043
- workspaceId: cleanString3(principalInput.workspaceId),
2200
+ tenantId: cleanString4(principalInput.tenantId),
2201
+ workspaceId: cleanString4(principalInput.workspaceId),
2044
2202
  roles: cleanStringList2(principalInput.roles),
2045
2203
  scopes: cleanStringList2(principalInput.scopes)
2046
2204
  };
@@ -2065,7 +2223,7 @@ function buildPolicyInput(identity, input) {
2065
2223
  "tenant_missing",
2066
2224
  "tenantId"
2067
2225
  );
2068
- const workspaceId = cleanString3(input.workspaceId ?? identity.workspaceId);
2226
+ const workspaceId = cleanString4(input.workspaceId ?? identity.workspaceId);
2069
2227
  if (resourceRequiresWorkspace(input.resource) && !workspaceId) {
2070
2228
  throw new LucernAccessControlError(
2071
2229
  "workspace_missing",
@@ -3465,12 +3623,12 @@ function createGraphClient(config = {}) {
3465
3623
  }
3466
3624
 
3467
3625
  // ../sdk/src/topicsClient.ts
3468
- function cleanString4(value) {
3626
+ function cleanString5(value) {
3469
3627
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
3470
3628
  }
3471
3629
  function normalizeTopicRecord(value) {
3472
3630
  const record = asRecord(value);
3473
- const topicId = cleanString4(record.topicId) ?? cleanString4(record.id) ?? cleanString4(record._id);
3631
+ const topicId = cleanString5(record.topicId) ?? cleanString5(record.id) ?? cleanString5(record._id);
3474
3632
  return withTopicAlias({
3475
3633
  ...record,
3476
3634
  ...topicId ? { topicId } : {}
@@ -4683,7 +4841,7 @@ function createEmbeddingsClient(config = {}) {
4683
4841
  }
4684
4842
 
4685
4843
  // ../sdk/src/contextClient.ts
4686
- function cleanString5(value) {
4844
+ function cleanString6(value) {
4687
4845
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
4688
4846
  }
4689
4847
  function cleanNumber(value) {
@@ -4695,11 +4853,11 @@ function cleanBoolean(value) {
4695
4853
  function buildCompileContextRequest(topicIdOrInput = {}, input = {}) {
4696
4854
  const effectiveInput = typeof topicIdOrInput === "string" ? input : topicIdOrInput;
4697
4855
  const payload = {};
4698
- const topicId = typeof topicIdOrInput === "string" ? cleanString5(topicIdOrInput) : cleanString5(effectiveInput.topicId);
4856
+ const topicId = typeof topicIdOrInput === "string" ? cleanString6(topicIdOrInput) : cleanString6(effectiveInput.topicId);
4699
4857
  if (topicId) {
4700
4858
  payload.topicId = topicId;
4701
4859
  }
4702
- const query5 = cleanString5(effectiveInput.query);
4860
+ const query5 = cleanString6(effectiveInput.query);
4703
4861
  if (query5) {
4704
4862
  payload.query = query5;
4705
4863
  }
@@ -4707,7 +4865,7 @@ function buildCompileContextRequest(topicIdOrInput = {}, input = {}) {
4707
4865
  if (budget !== void 0) {
4708
4866
  payload.budget = budget;
4709
4867
  }
4710
- const ranking = cleanString5(effectiveInput.ranking) ?? cleanString5(effectiveInput.rankingProfile);
4868
+ const ranking = cleanString6(effectiveInput.ranking) ?? cleanString6(effectiveInput.rankingProfile);
4711
4869
  if (ranking) {
4712
4870
  payload.ranking = ranking;
4713
4871
  }
@@ -4723,7 +4881,7 @@ function buildCompileContextRequest(topicIdOrInput = {}, input = {}) {
4723
4881
  if (includeEntities !== void 0) {
4724
4882
  payload.includeEntities = includeEntities;
4725
4883
  }
4726
- const mode = cleanString5(effectiveInput.mode);
4884
+ const mode = cleanString6(effectiveInput.mode);
4727
4885
  if (mode) {
4728
4886
  payload.mode = mode;
4729
4887
  }
@@ -4731,11 +4889,11 @@ function buildCompileContextRequest(topicIdOrInput = {}, input = {}) {
4731
4889
  if (includeFailures !== void 0) {
4732
4890
  payload.includeFailures = includeFailures;
4733
4891
  }
4734
- const worktreeId = cleanString5(effectiveInput.worktreeId);
4892
+ const worktreeId = cleanString6(effectiveInput.worktreeId);
4735
4893
  if (worktreeId) {
4736
4894
  payload.worktreeId = worktreeId;
4737
4895
  }
4738
- const sessionId = cleanString5(effectiveInput.sessionId);
4896
+ const sessionId = cleanString6(effectiveInput.sessionId);
4739
4897
  if (sessionId) {
4740
4898
  payload.sessionId = sessionId;
4741
4899
  }
@@ -5744,6 +5902,7 @@ var FUNCTION_SURFACE_METHOD_PATHS = [
5744
5902
  "contracts.evaluateContract",
5745
5903
  "contracts.getContractStatus",
5746
5904
  "contradictions.flagContradiction",
5905
+ "controlPlane.identity.resolveInteractivePrincipal",
5747
5906
  "coordination.broadcastMessage",
5748
5907
  "coordination.claimFiles",
5749
5908
  "coordination.endSession",
@@ -5949,6 +6108,7 @@ var CONTRACTS = {
5949
6108
  "remove_edges_between": { method: "DELETE", path: "/edges/between", kind: "mutation", idempotent: true, surfaceIntent: "mcp_analysis" },
5950
6109
  "remove_lens_from_topic": { method: "DELETE", path: "/lenses/apply", kind: "mutation", idempotent: true, surfaceIntent: "mcp_workflow" },
5951
6110
  "resolve_effective_ontology": { method: "POST", path: "/ontologies/effective", kind: "query", idempotent: false, surfaceIntent: "mcp_workflow" },
6111
+ "resolve_interactive_principal": { method: "POST", path: "/control-plane/identity/resolve-interactive-principal", kind: "query", idempotent: false, surfaceIntent: "mcp_core" },
5952
6112
  "run_graph_intelligence_query": { method: "POST", path: "/graph-intelligence/run", kind: "query", idempotent: false, surfaceIntent: "mcp_analysis" },
5953
6113
  "search_beliefs": { method: "POST", path: "/beliefs/search", kind: "query", idempotent: false, surfaceIntent: "mcp_core" },
5954
6114
  "search_evidence": { method: "POST", path: "/evidence/search", kind: "query", idempotent: false, surfaceIntent: "mcp_core" },
@@ -6331,6 +6491,9 @@ function createFunctionSurfaceClient(config = {}) {
6331
6491
  resolveEffectiveOntology(input = {}, idempotencyKey) {
6332
6492
  return execute("resolve_effective_ontology", input, idempotencyKey);
6333
6493
  },
6494
+ resolveInteractivePrincipal(input = {}, idempotencyKey) {
6495
+ return execute("resolve_interactive_principal", input, idempotencyKey);
6496
+ },
6334
6497
  runGraphIntelligenceQuery(input = {}, idempotencyKey) {
6335
6498
  return execute("run_graph_intelligence_query", input, idempotencyKey);
6336
6499
  },
@@ -6591,7 +6754,7 @@ var ORG_GRAPH_SEARCH_FIELDS = [
6591
6754
  "cursor",
6592
6755
  "provenanceScope"
6593
6756
  ];
6594
- function cleanString6(value, label) {
6757
+ function cleanString7(value, label) {
6595
6758
  const normalized = value?.trim();
6596
6759
  if (!normalized) {
6597
6760
  throw new Error(`${label} is required`);
@@ -6613,9 +6776,9 @@ function searchBody(input) {
6613
6776
  "orgGraphSearch.search"
6614
6777
  );
6615
6778
  return {
6616
- tenantId: cleanString6(input.tenantId, "tenantId"),
6617
- workspaceId: cleanString6(input.workspaceId, "workspaceId"),
6618
- query: cleanString6(input.query, "query"),
6779
+ tenantId: cleanString7(input.tenantId, "tenantId"),
6780
+ workspaceId: cleanString7(input.workspaceId, "workspaceId"),
6781
+ query: cleanString7(input.query, "query"),
6619
6782
  nodeTypes: input.nodeTypes,
6620
6783
  minConfidence: input.minConfidence,
6621
6784
  limit: input.limit,
@@ -6625,8 +6788,8 @@ function searchBody(input) {
6625
6788
  }
6626
6789
  function listQuery2(input) {
6627
6790
  return {
6628
- tenantId: cleanString6(input.tenantId, "tenantId"),
6629
- workspaceId: cleanString6(input.workspaceId, "workspaceId"),
6791
+ tenantId: cleanString7(input.tenantId, "tenantId"),
6792
+ workspaceId: cleanString7(input.workspaceId, "workspaceId"),
6630
6793
  nodeTypes: input.nodeTypes?.join(","),
6631
6794
  minConfidence: input.minConfidence,
6632
6795
  limit: input.limit,
@@ -6660,8 +6823,8 @@ function createOrgGraphSearchClient(config = {}) {
6660
6823
  return gateway.request({
6661
6824
  path: `/api/platform/v1/org-graph-search/nodes/${nodePath}${toQueryString(
6662
6825
  {
6663
- tenantId: cleanString6(input.tenantId, "tenantId"),
6664
- workspaceId: cleanString6(input.workspaceId, "workspaceId"),
6826
+ tenantId: cleanString7(input.tenantId, "tenantId"),
6827
+ workspaceId: cleanString7(input.workspaceId, "workspaceId"),
6665
6828
  globalId: nodeId ? void 0 : globalId
6666
6829
  }
6667
6830
  )}`
@@ -7626,7 +7789,7 @@ function createToolRegistryClient(config = {}) {
7626
7789
  }
7627
7790
 
7628
7791
  // ../sdk/src/version.ts
7629
- var LUCERN_SDK_VERSION = "0.3.0-alpha.12";
7792
+ var LUCERN_SDK_VERSION = "0.3.0-alpha.14";
7630
7793
 
7631
7794
  // ../sdk/src/workflowClient.ts
7632
7795
  function normalizeLensQuery(value) {
@@ -8103,6 +8266,7 @@ function createLucernClient(config = {}) {
8103
8266
  const ontologyLinksClient = createOntologyLinksClient(gatewayConfig);
8104
8267
  const orgGraphSearchClient = createOrgGraphSearchClient(gatewayConfig);
8105
8268
  const functionSurfaceClient = createFunctionSurfaceClient(gatewayConfig);
8269
+ const controlPlaneClient = createControlPlaneClient(gatewayConfig);
8106
8270
  const toolRegistryClient = createToolRegistryClient(gatewayConfig);
8107
8271
  const modelRuntimeClient = createModelRuntimeClient(gatewayConfig);
8108
8272
  const packsClient = createPacksClient(gatewayConfig);
@@ -9766,9 +9930,16 @@ function createLucernClient(config = {}) {
9766
9930
  disable: packsClient.disable
9767
9931
  },
9768
9932
  nodes: nodesNamespace,
9933
+ controlPlane: {
9934
+ identity: {
9935
+ resolveInteractivePrincipal: controlPlaneClient.identity.resolveInteractivePrincipal
9936
+ },
9937
+ raw: controlPlaneClient
9938
+ },
9769
9939
  identity: {
9770
9940
  ...identityFacade,
9771
9941
  access: accessControlClient,
9942
+ resolveInteractivePrincipal: identityClient.resolveInteractivePrincipal,
9772
9943
  evaluatePolicy: identityClient.evaluatePolicy,
9773
9944
  recordPolicyDecision: identityClient.recordPolicyDecision,
9774
9945
  putSecretReference: identityClient.putSecretReference,
@@ -9813,6 +9984,7 @@ function createLucernClient(config = {}) {
9813
9984
  ontologyLinks: ontologyLinksClient,
9814
9985
  orgGraphSearch: orgGraphSearchClient,
9815
9986
  functionSurface: functionSurfaceClient,
9987
+ controlPlane: controlPlaneClient,
9816
9988
  toolRegistry: toolRegistryClient,
9817
9989
  modelRuntime: modelRuntimeClient,
9818
9990
  packs: packsClient,
@@ -9830,7 +10002,7 @@ function createLucernClient(config = {}) {
9830
10002
  }
9831
10003
 
9832
10004
  // ../sdk/src/facade/context.ts
9833
- function cleanString7(value) {
10005
+ function cleanString8(value) {
9834
10006
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
9835
10007
  }
9836
10008
  function cleanNumber2(value) {
@@ -9842,11 +10014,11 @@ function cleanBoolean2(value) {
9842
10014
  function buildCompileContextRequest2(topicIdOrInput = {}, input = {}) {
9843
10015
  const effectiveInput = typeof topicIdOrInput === "string" ? input : topicIdOrInput;
9844
10016
  const payload = {};
9845
- const topicId = typeof topicIdOrInput === "string" ? cleanString7(topicIdOrInput) : cleanString7(effectiveInput.topicId);
10017
+ const topicId = typeof topicIdOrInput === "string" ? cleanString8(topicIdOrInput) : cleanString8(effectiveInput.topicId);
9846
10018
  if (topicId) {
9847
10019
  payload.topicId = topicId;
9848
10020
  }
9849
- const query5 = cleanString7(effectiveInput.query);
10021
+ const query5 = cleanString8(effectiveInput.query);
9850
10022
  if (query5) {
9851
10023
  payload.query = query5;
9852
10024
  }
@@ -9854,7 +10026,7 @@ function buildCompileContextRequest2(topicIdOrInput = {}, input = {}) {
9854
10026
  if (budget !== void 0) {
9855
10027
  payload.budget = budget;
9856
10028
  }
9857
- const ranking = cleanString7(effectiveInput.ranking) ?? cleanString7(effectiveInput.rankingProfile);
10029
+ const ranking = cleanString8(effectiveInput.ranking) ?? cleanString8(effectiveInput.rankingProfile);
9858
10030
  if (ranking) {
9859
10031
  payload.ranking = ranking;
9860
10032
  }
@@ -9870,7 +10042,7 @@ function buildCompileContextRequest2(topicIdOrInput = {}, input = {}) {
9870
10042
  if (includeEntities !== void 0) {
9871
10043
  payload.includeEntities = includeEntities;
9872
10044
  }
9873
- const mode = cleanString7(effectiveInput.mode);
10045
+ const mode = cleanString8(effectiveInput.mode);
9874
10046
  if (mode) {
9875
10047
  payload.mode = mode;
9876
10048
  }
@@ -9878,11 +10050,11 @@ function buildCompileContextRequest2(topicIdOrInput = {}, input = {}) {
9878
10050
  if (includeFailures !== void 0) {
9879
10051
  payload.includeFailures = includeFailures;
9880
10052
  }
9881
- const worktreeId = cleanString7(effectiveInput.worktreeId);
10053
+ const worktreeId = cleanString8(effectiveInput.worktreeId);
9882
10054
  if (worktreeId) {
9883
10055
  payload.worktreeId = worktreeId;
9884
10056
  }
9885
- const sessionId = cleanString7(effectiveInput.sessionId);
10057
+ const sessionId = cleanString8(effectiveInput.sessionId);
9886
10058
  if (sessionId) {
9887
10059
  payload.sessionId = sessionId;
9888
10060
  }
@@ -11304,7 +11476,13 @@ var SESSION_AUTH_MODES = [
11304
11476
  "tenant_api_key",
11305
11477
  "session_token"
11306
11478
  ];
11307
- var SESSION_PRINCIPAL_TYPES = ["human", "service", "agent"];
11479
+ var SESSION_PRINCIPAL_TYPES = [
11480
+ "human",
11481
+ "service",
11482
+ "agent",
11483
+ "group",
11484
+ "external_viewer"
11485
+ ];
11308
11486
  var SESSION_LIFECYCLE_STATUSES = [
11309
11487
  "active",
11310
11488
  "expired",
@@ -11317,6 +11495,12 @@ function inferSessionPrincipalType(principalId) {
11317
11495
  if (principalId.startsWith("agent:")) {
11318
11496
  return "agent";
11319
11497
  }
11498
+ if (principalId.startsWith("group:")) {
11499
+ return "group";
11500
+ }
11501
+ if (principalId.startsWith("external:") || principalId.startsWith("external_viewer:")) {
11502
+ return "external_viewer";
11503
+ }
11320
11504
  return "service";
11321
11505
  }
11322
11506
  function normalizeDelegationChain(args) {
@@ -13789,7 +13973,7 @@ var IDENTITY_WHOAMI = {
13789
13973
  description: "Canonical identity summary for the current session",
13790
13974
  fields: {
13791
13975
  principalId: "string \u2014 canonical federated principal identifier",
13792
- principalType: "string \u2014 human, service, or agent",
13976
+ principalType: "string \u2014 human, service, agent, group, or external_viewer",
13793
13977
  tenantId: "string | undefined \u2014 resolved tenant scope",
13794
13978
  workspaceId: "string | undefined \u2014 resolved workspace scope",
13795
13979
  scopes: "string[] | undefined \u2014 granted scopes for this session",
@@ -13800,6 +13984,49 @@ var IDENTITY_WHOAMI = {
13800
13984
  ontologyPrimitive: "identity",
13801
13985
  tier: "workhorse"
13802
13986
  };
13987
+ var RESOLVE_INTERACTIVE_PRINCIPAL = {
13988
+ name: "resolve_interactive_principal",
13989
+ 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.",
13990
+ parameters: {
13991
+ clerkId: {
13992
+ type: "string",
13993
+ description: "Authenticated Clerk subject (`sub`). Clerk proves identity only; it is not the authorization record."
13994
+ },
13995
+ tenantId: {
13996
+ type: "string",
13997
+ description: "Optional tenant scope. Omit only when the Clerk alias is globally unambiguous."
13998
+ },
13999
+ workspaceId: {
14000
+ type: "string",
14001
+ description: "Optional workspace scope. Required when the principal has access to multiple workspaces and no default can be inferred."
14002
+ },
14003
+ providerProjectId: {
14004
+ type: "string",
14005
+ description: "Optional Clerk project or provider instance id for tenants with multiple identity providers."
14006
+ }
14007
+ },
14008
+ required: ["clerkId"],
14009
+ response: {
14010
+ description: "Permit-backed Lucern principal context for tenant SDK bootstrap",
14011
+ fields: {
14012
+ principalId: "string \u2014 canonical Lucern principal identifier",
14013
+ principalType: "string \u2014 human, service, agent, group, or external_viewer",
14014
+ clerkId: "string \u2014 authenticated Clerk subject alias",
14015
+ tenantId: "string \u2014 resolved tenant scope",
14016
+ workspaceId: "string | null \u2014 resolved workspace scope",
14017
+ roles: "string[] \u2014 effective Permit roles",
14018
+ scopes: "string[] \u2014 effective scopes derived from Permit/control-plane projection",
14019
+ groupIds: "string[] \u2014 active Permit group memberships",
14020
+ principalStatus: "string \u2014 active, invited, suspended, disabled, revoked, or missing",
14021
+ tenantStatus: "string \u2014 projected tenant resource status",
14022
+ workspaceStatus: "string \u2014 projected workspace resource status",
14023
+ permit: "object \u2014 Permit subject, tenant, and optional workspace tuple"
14024
+ }
14025
+ },
14026
+ ownerModule: "control-plane",
14027
+ ontologyPrimitive: "identity",
14028
+ tier: "workhorse"
14029
+ };
13803
14030
  var COMPILE_CONTEXT = {
13804
14031
  name: "compile_context",
13805
14032
  description: "Compile a focused reasoning context. If topicId is omitted, Lucern resolves the best topic from the query. Like `git log --graph --decorate` for the reasoning substrate \u2014 returns the canonical Pillar 3 context pack through the public API shape.",
@@ -15702,6 +15929,7 @@ var MCP_TOOL_CONTRACTS = {
15702
15929
  update_worktree_targets: UPDATE_WORKTREE_TARGETS,
15703
15930
  update_worktree_metadata: UPDATE_WORKTREE_METADATA,
15704
15931
  identity_whoami: IDENTITY_WHOAMI,
15932
+ resolve_interactive_principal: RESOLVE_INTERACTIVE_PRINCIPAL,
15705
15933
  compile_context: COMPILE_CONTEXT,
15706
15934
  record_scope_learning: RECORD_SCOPE_LEARNING,
15707
15935
  pipeline_snapshot: PIPELINE_SNAPSHOT,
@@ -15831,6 +16059,7 @@ function entries(names, surfaceClass, surfaceIntent, surfaces, rationale) {
15831
16059
  var MCP_CORE_OPERATION_NAMES = [
15832
16060
  "compile_context",
15833
16061
  "identity_whoami",
16062
+ "resolve_interactive_principal",
15834
16063
  "check_permission",
15835
16064
  "filter_by_permission",
15836
16065
  "create_belief",
@@ -17912,6 +18141,35 @@ defineTable({
17912
18141
  { kind: "index", name: "by_source", columns: ["source"] }
17913
18142
  ]
17914
18143
  });
18144
+ defineTable({
18145
+ name: "domainEvents",
18146
+ component: "kernel",
18147
+ category: "events",
18148
+ shape: z.object({
18149
+ "eventId": z.string(),
18150
+ "type": z.string(),
18151
+ "version": z.string(),
18152
+ "timestamp": z.number(),
18153
+ "tenantId": z.string().optional(),
18154
+ "workspaceId": z.string().optional(),
18155
+ "topicId": z.string(),
18156
+ "resourceId": z.string(),
18157
+ "resourceType": z.string(),
18158
+ "actorId": z.string(),
18159
+ "actorType": z.enum(["human", "agent", "service"]),
18160
+ "data": z.record(z.any()),
18161
+ "correlationId": z.string().optional(),
18162
+ "expiresAt": z.number()
18163
+ }),
18164
+ indices: [
18165
+ { kind: "index", name: "by_eventId", columns: ["eventId"] },
18166
+ { kind: "index", name: "by_topic_timestamp", columns: ["topicId", "timestamp"] },
18167
+ { kind: "index", name: "by_tenant_workspace_timestamp", columns: ["tenantId", "workspaceId", "timestamp"] },
18168
+ { kind: "index", name: "by_type_timestamp", columns: ["type", "timestamp"] },
18169
+ { kind: "index", name: "by_resource", columns: ["resourceType", "resourceId", "timestamp"] },
18170
+ { kind: "index", name: "by_expiresAt", columns: ["expiresAt"] }
18171
+ ]
18172
+ });
17915
18173
  defineTable({
17916
18174
  name: "beliefConfidence",
17917
18175
  component: "kernel",
@@ -21318,7 +21576,10 @@ defineTable({
21318
21576
  }),
21319
21577
  indices: [
21320
21578
  { kind: "index", name: "by_principalId", columns: ["principalId"] },
21579
+ { kind: "index", name: "by_provider_subject", columns: ["provider", "providerSubjectId"] },
21580
+ { kind: "index", name: "by_provider_project_subject", columns: ["provider", "providerProjectId", "providerSubjectId"] },
21321
21581
  { kind: "index", name: "by_tenant_provider_subject", columns: ["tenantId", "provider", "providerSubjectId"] },
21582
+ { kind: "index", name: "by_tenant_provider_project_subject", columns: ["tenantId", "provider", "providerProjectId", "providerSubjectId"] },
21322
21583
  {
21323
21584
  kind: "index",
21324
21585
  name: "by_tenant_provider_alias",
@@ -24686,6 +24947,40 @@ var GENERATED_INFISICAL_RUNTIME_ENV = {
24686
24947
  ],
24687
24948
  "description": "Canonical Lucern API gateway URL. Canonical Lucern API gateway base URL. Older names remain aliases only."
24688
24949
  },
24950
+ {
24951
+ "secretId": "platform.clerk.webhook-secret",
24952
+ "canonicalName": "LUCERN_CLERK_WEBHOOK_SECRET",
24953
+ "envNames": [
24954
+ "CLERK_WEBHOOK_SECRET",
24955
+ "CLERK_WEBHOOK_SIGNING_SECRET",
24956
+ "LUCERN_CLERK_WEBHOOK_SECRET"
24957
+ ],
24958
+ "aliases": [
24959
+ "CLERK_WEBHOOK_SECRET",
24960
+ "CLERK_WEBHOOK_SIGNING_SECRET"
24961
+ ],
24962
+ "writeNames": [
24963
+ "LUCERN_CLERK_WEBHOOK_SECRET"
24964
+ ],
24965
+ "required": true,
24966
+ "secret": true,
24967
+ "public": false,
24968
+ "sourcePath": "/platform/auth",
24969
+ "environmentPolicy": "environment_specific",
24970
+ "consumers": [
24971
+ "lucern-gateway"
24972
+ ],
24973
+ "destinations": [
24974
+ {
24975
+ "kind": "vercel",
24976
+ "target": "lucern-gateway",
24977
+ "writeNames": [
24978
+ "LUCERN_CLERK_WEBHOOK_SECRET"
24979
+ ]
24980
+ }
24981
+ ],
24982
+ "description": "Lucern-owned Clerk/Svix webhook signing secret used by the gateway to verify Clerk identity and organization events before projecting them into Permit."
24983
+ },
24689
24984
  {
24690
24985
  "canonicalName": "LUCERN_CLI_SESSION_TTL_MS",
24691
24986
  "envNames": [
@@ -27098,7 +27393,13 @@ function surfaceContract(args) {
27098
27393
  scopes: args.scopes ?? [
27099
27394
  args.kind === "query" ? `${args.domain}.read` : `${args.domain}.write`
27100
27395
  ],
27101
- allowedPrincipalTypes: ["user", "service", "agent"]
27396
+ allowedPrincipalTypes: [
27397
+ "user",
27398
+ "service",
27399
+ "agent",
27400
+ "group",
27401
+ "external_viewer"
27402
+ ]
27102
27403
  },
27103
27404
  convex: args.convex,
27104
27405
  gateway: args.gateway,
@@ -27240,8 +27541,6 @@ var contextContracts = [
27240
27541
  args: observationContextArgs
27241
27542
  })
27242
27543
  ];
27243
-
27244
- // ../contracts/src/function-registry/identity.ts
27245
27544
  var withPrincipal = (input, context) => ({
27246
27545
  ...input,
27247
27546
  tenantId: input.tenantId ?? context.tenantId,
@@ -27267,6 +27566,28 @@ var identityContracts = [
27267
27566
  inputProjection: withPrincipal
27268
27567
  }
27269
27568
  }),
27569
+ surfaceContract({
27570
+ name: "resolve_interactive_principal",
27571
+ kind: "query",
27572
+ domain: "controlPlane",
27573
+ surfaceClass: "platform_public",
27574
+ method: "POST",
27575
+ path: "/control-plane/identity/resolve-interactive-principal",
27576
+ sdkNamespace: "controlPlane.identity",
27577
+ sdkMethod: "resolveInteractivePrincipal",
27578
+ summary: "Resolve an authenticated Clerk user into a Permit-backed Lucern principal context.",
27579
+ args: z.object({
27580
+ clerkId: z.string().min(1),
27581
+ tenantId: z.string().min(1).optional(),
27582
+ workspaceId: z.string().min(1).optional(),
27583
+ providerProjectId: z.string().min(1).optional()
27584
+ }),
27585
+ convex: {
27586
+ module: "identity",
27587
+ functionName: "resolveInteractivePrincipal",
27588
+ kind: "query"
27589
+ }
27590
+ }),
27270
27591
  surfaceContract({
27271
27592
  name: "check_permission",
27272
27593
  kind: "query",
@@ -31071,6 +31392,13 @@ var TENANT_BOOTSTRAP_TABLE_REQUIREMENTS = [
31071
31392
  copyMode: "none",
31072
31393
  description: "Deliberation sessions are created by tenant workflows."
31073
31394
  },
31395
+ {
31396
+ component: "kernel",
31397
+ table: "domainEvents",
31398
+ prepopulation: "runtime_log",
31399
+ copyMode: "none",
31400
+ description: "Domain event rows are append-only runtime audit/exhaust data."
31401
+ },
31074
31402
  {
31075
31403
  component: "kernel",
31076
31404
  table: "epistemicAudit",
@@ -34309,7 +34637,7 @@ function createLucernStandaloneMcpServer(options) {
34309
34637
  });
34310
34638
  const server = new McpServer({
34311
34639
  name: "lucern-mcp",
34312
- version: "0.3.0-alpha.12"
34640
+ version: "0.3.0-alpha.14"
34313
34641
  });
34314
34642
  registerTools(server, runtime);
34315
34643
  const resources = registerResources(server, runtime, observationStore);