@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.
package/dist/index.js CHANGED
@@ -1593,6 +1593,35 @@ defineTable({
1593
1593
  { kind: "index", name: "by_source", columns: ["source"] }
1594
1594
  ]
1595
1595
  });
1596
+ defineTable({
1597
+ name: "domainEvents",
1598
+ component: "kernel",
1599
+ category: "events",
1600
+ shape: z.object({
1601
+ "eventId": z.string(),
1602
+ "type": z.string(),
1603
+ "version": z.string(),
1604
+ "timestamp": z.number(),
1605
+ "tenantId": z.string().optional(),
1606
+ "workspaceId": z.string().optional(),
1607
+ "topicId": z.string(),
1608
+ "resourceId": z.string(),
1609
+ "resourceType": z.string(),
1610
+ "actorId": z.string(),
1611
+ "actorType": z.enum(["human", "agent", "service"]),
1612
+ "data": z.record(z.any()),
1613
+ "correlationId": z.string().optional(),
1614
+ "expiresAt": z.number()
1615
+ }),
1616
+ indices: [
1617
+ { kind: "index", name: "by_eventId", columns: ["eventId"] },
1618
+ { kind: "index", name: "by_topic_timestamp", columns: ["topicId", "timestamp"] },
1619
+ { kind: "index", name: "by_tenant_workspace_timestamp", columns: ["tenantId", "workspaceId", "timestamp"] },
1620
+ { kind: "index", name: "by_type_timestamp", columns: ["type", "timestamp"] },
1621
+ { kind: "index", name: "by_resource", columns: ["resourceType", "resourceId", "timestamp"] },
1622
+ { kind: "index", name: "by_expiresAt", columns: ["expiresAt"] }
1623
+ ]
1624
+ });
1596
1625
  defineTable({
1597
1626
  name: "beliefConfidence",
1598
1627
  component: "kernel",
@@ -4999,7 +5028,10 @@ defineTable({
4999
5028
  }),
5000
5029
  indices: [
5001
5030
  { kind: "index", name: "by_principalId", columns: ["principalId"] },
5031
+ { kind: "index", name: "by_provider_subject", columns: ["provider", "providerSubjectId"] },
5032
+ { kind: "index", name: "by_provider_project_subject", columns: ["provider", "providerProjectId", "providerSubjectId"] },
5002
5033
  { kind: "index", name: "by_tenant_provider_subject", columns: ["tenantId", "provider", "providerSubjectId"] },
5034
+ { kind: "index", name: "by_tenant_provider_project_subject", columns: ["tenantId", "provider", "providerProjectId", "providerSubjectId"] },
5003
5035
  {
5004
5036
  kind: "index",
5005
5037
  name: "by_tenant_provider_alias",
@@ -8367,6 +8399,40 @@ var GENERATED_INFISICAL_RUNTIME_ENV = {
8367
8399
  ],
8368
8400
  "description": "Canonical Lucern API gateway URL. Canonical Lucern API gateway base URL. Older names remain aliases only."
8369
8401
  },
8402
+ {
8403
+ "secretId": "platform.clerk.webhook-secret",
8404
+ "canonicalName": "LUCERN_CLERK_WEBHOOK_SECRET",
8405
+ "envNames": [
8406
+ "CLERK_WEBHOOK_SECRET",
8407
+ "CLERK_WEBHOOK_SIGNING_SECRET",
8408
+ "LUCERN_CLERK_WEBHOOK_SECRET"
8409
+ ],
8410
+ "aliases": [
8411
+ "CLERK_WEBHOOK_SECRET",
8412
+ "CLERK_WEBHOOK_SIGNING_SECRET"
8413
+ ],
8414
+ "writeNames": [
8415
+ "LUCERN_CLERK_WEBHOOK_SECRET"
8416
+ ],
8417
+ "required": true,
8418
+ "secret": true,
8419
+ "public": false,
8420
+ "sourcePath": "/platform/auth",
8421
+ "environmentPolicy": "environment_specific",
8422
+ "consumers": [
8423
+ "lucern-gateway"
8424
+ ],
8425
+ "destinations": [
8426
+ {
8427
+ "kind": "vercel",
8428
+ "target": "lucern-gateway",
8429
+ "writeNames": [
8430
+ "LUCERN_CLERK_WEBHOOK_SECRET"
8431
+ ]
8432
+ }
8433
+ ],
8434
+ "description": "Lucern-owned Clerk/Svix webhook signing secret used by the gateway to verify Clerk identity and organization events before projecting them into Permit."
8435
+ },
8370
8436
  {
8371
8437
  "canonicalName": "LUCERN_CLI_SESSION_TTL_MS",
8372
8438
  "envNames": [
@@ -12826,7 +12892,7 @@ var IDENTITY_WHOAMI = {
12826
12892
  description: "Canonical identity summary for the current session",
12827
12893
  fields: {
12828
12894
  principalId: "string \u2014 canonical federated principal identifier",
12829
- principalType: "string \u2014 human, service, or agent",
12895
+ principalType: "string \u2014 human, service, agent, group, or external_viewer",
12830
12896
  tenantId: "string | undefined \u2014 resolved tenant scope",
12831
12897
  workspaceId: "string | undefined \u2014 resolved workspace scope",
12832
12898
  scopes: "string[] | undefined \u2014 granted scopes for this session",
@@ -12837,6 +12903,49 @@ var IDENTITY_WHOAMI = {
12837
12903
  ontologyPrimitive: "identity",
12838
12904
  tier: "workhorse"
12839
12905
  };
12906
+ var RESOLVE_INTERACTIVE_PRINCIPAL = {
12907
+ name: "resolve_interactive_principal",
12908
+ 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.",
12909
+ parameters: {
12910
+ clerkId: {
12911
+ type: "string",
12912
+ description: "Authenticated Clerk subject (`sub`). Clerk proves identity only; it is not the authorization record."
12913
+ },
12914
+ tenantId: {
12915
+ type: "string",
12916
+ description: "Optional tenant scope. Omit only when the Clerk alias is globally unambiguous."
12917
+ },
12918
+ workspaceId: {
12919
+ type: "string",
12920
+ description: "Optional workspace scope. Required when the principal has access to multiple workspaces and no default can be inferred."
12921
+ },
12922
+ providerProjectId: {
12923
+ type: "string",
12924
+ description: "Optional Clerk project or provider instance id for tenants with multiple identity providers."
12925
+ }
12926
+ },
12927
+ required: ["clerkId"],
12928
+ response: {
12929
+ description: "Permit-backed Lucern principal context for tenant SDK bootstrap",
12930
+ fields: {
12931
+ principalId: "string \u2014 canonical Lucern principal identifier",
12932
+ principalType: "string \u2014 human, service, agent, group, or external_viewer",
12933
+ clerkId: "string \u2014 authenticated Clerk subject alias",
12934
+ tenantId: "string \u2014 resolved tenant scope",
12935
+ workspaceId: "string | null \u2014 resolved workspace scope",
12936
+ roles: "string[] \u2014 effective Permit roles",
12937
+ scopes: "string[] \u2014 effective scopes derived from Permit/control-plane projection",
12938
+ groupIds: "string[] \u2014 active Permit group memberships",
12939
+ principalStatus: "string \u2014 active, invited, suspended, disabled, revoked, or missing",
12940
+ tenantStatus: "string \u2014 projected tenant resource status",
12941
+ workspaceStatus: "string \u2014 projected workspace resource status",
12942
+ permit: "object \u2014 Permit subject, tenant, and optional workspace tuple"
12943
+ }
12944
+ },
12945
+ ownerModule: "control-plane",
12946
+ ontologyPrimitive: "identity",
12947
+ tier: "workhorse"
12948
+ };
12840
12949
  var COMPILE_CONTEXT = {
12841
12950
  name: "compile_context",
12842
12951
  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.",
@@ -14739,6 +14848,7 @@ var MCP_TOOL_CONTRACTS = {
14739
14848
  update_worktree_targets: UPDATE_WORKTREE_TARGETS,
14740
14849
  update_worktree_metadata: UPDATE_WORKTREE_METADATA,
14741
14850
  identity_whoami: IDENTITY_WHOAMI,
14851
+ resolve_interactive_principal: RESOLVE_INTERACTIVE_PRINCIPAL,
14742
14852
  compile_context: COMPILE_CONTEXT,
14743
14853
  record_scope_learning: RECORD_SCOPE_LEARNING,
14744
14854
  pipeline_snapshot: PIPELINE_SNAPSHOT,
@@ -14868,6 +14978,7 @@ function entries(names, surfaceClass, surfaceIntent, surfaces, rationale) {
14868
14978
  var MCP_CORE_OPERATION_NAMES = [
14869
14979
  "compile_context",
14870
14980
  "identity_whoami",
14981
+ "resolve_interactive_principal",
14871
14982
  "check_permission",
14872
14983
  "filter_by_permission",
14873
14984
  "create_belief",
@@ -15421,7 +15532,13 @@ function surfaceContract(args) {
15421
15532
  scopes: args.scopes ?? [
15422
15533
  args.kind === "query" ? `${args.domain}.read` : `${args.domain}.write`
15423
15534
  ],
15424
- allowedPrincipalTypes: ["user", "service", "agent"]
15535
+ allowedPrincipalTypes: [
15536
+ "user",
15537
+ "service",
15538
+ "agent",
15539
+ "group",
15540
+ "external_viewer"
15541
+ ]
15425
15542
  },
15426
15543
  convex: args.convex,
15427
15544
  gateway: args.gateway,
@@ -15563,8 +15680,6 @@ var contextContracts = [
15563
15680
  args: observationContextArgs
15564
15681
  })
15565
15682
  ];
15566
-
15567
- // ../contracts/src/function-registry/identity.ts
15568
15683
  var withPrincipal = (input, context) => ({
15569
15684
  ...input,
15570
15685
  tenantId: input.tenantId ?? context.tenantId,
@@ -15590,6 +15705,28 @@ var identityContracts = [
15590
15705
  inputProjection: withPrincipal
15591
15706
  }
15592
15707
  }),
15708
+ surfaceContract({
15709
+ name: "resolve_interactive_principal",
15710
+ kind: "query",
15711
+ domain: "controlPlane",
15712
+ surfaceClass: "platform_public",
15713
+ method: "POST",
15714
+ path: "/control-plane/identity/resolve-interactive-principal",
15715
+ sdkNamespace: "controlPlane.identity",
15716
+ sdkMethod: "resolveInteractivePrincipal",
15717
+ summary: "Resolve an authenticated Clerk user into a Permit-backed Lucern principal context.",
15718
+ args: z.object({
15719
+ clerkId: z.string().min(1),
15720
+ tenantId: z.string().min(1).optional(),
15721
+ workspaceId: z.string().min(1).optional(),
15722
+ providerProjectId: z.string().min(1).optional()
15723
+ }),
15724
+ convex: {
15725
+ module: "identity",
15726
+ functionName: "resolveInteractivePrincipal",
15727
+ kind: "query"
15728
+ }
15729
+ }),
15593
15730
  surfaceContract({
15594
15731
  name: "check_permission",
15595
15732
  kind: "query",
@@ -19394,6 +19531,13 @@ var TENANT_BOOTSTRAP_TABLE_REQUIREMENTS = [
19394
19531
  copyMode: "none",
19395
19532
  description: "Deliberation sessions are created by tenant workflows."
19396
19533
  },
19534
+ {
19535
+ component: "kernel",
19536
+ table: "domainEvents",
19537
+ prepopulation: "runtime_log",
19538
+ copyMode: "none",
19539
+ description: "Domain event rows are append-only runtime audit/exhaust data."
19540
+ },
19397
19541
  {
19398
19542
  component: "kernel",
19399
19543
  table: "epistemicAudit",
@@ -20526,6 +20670,7 @@ __export(src_exports, {
20526
20670
  LUCERN_SDK_VERSION: () => LUCERN_SDK_VERSION,
20527
20671
  LucernAccessControlError: () => LucernAccessControlError,
20528
20672
  LucernApiError: () => LucernApiError,
20673
+ LucernControlPlaneIdentityError: () => LucernControlPlaneIdentityError,
20529
20674
  LucernSdkAuthContextError: () => LucernSdkAuthContextError,
20530
20675
  MANAGE_WRITE_POLICY: () => MANAGE_WRITE_POLICY,
20531
20676
  MATCH_ENTITY_TYPE: () => MATCH_ENTITY_TYPE,
@@ -20557,6 +20702,7 @@ __export(src_exports, {
20557
20702
  REMOVE_EDGES_BETWEEN: () => REMOVE_EDGES_BETWEEN,
20558
20703
  REMOVE_LENS_FROM_TOPIC: () => REMOVE_LENS_FROM_TOPIC,
20559
20704
  RESOLVE_EFFECTIVE_ONTOLOGY: () => RESOLVE_EFFECTIVE_ONTOLOGY,
20705
+ RESOLVE_INTERACTIVE_PRINCIPAL: () => RESOLVE_INTERACTIVE_PRINCIPAL,
20560
20706
  RUN_GRAPH_INTELLIGENCE_QUERY: () => RUN_GRAPH_INTELLIGENCE_QUERY,
20561
20707
  SEARCH_BELIEFS: () => SEARCH_BELIEFS,
20562
20708
  SEARCH_EVIDENCE: () => SEARCH_EVIDENCE,
@@ -20622,6 +20768,8 @@ __export(src_exports, {
20622
20768
  createCanonicalAuthHeaders: () => createCanonicalAuthHeaders,
20623
20769
  createContextClient: () => createContextClient,
20624
20770
  createContextFacade: () => createContextFacade,
20771
+ createControlPlaneClient: () => createControlPlaneClient,
20772
+ createControlPlaneIdentityClient: () => createControlPlaneIdentityClient,
20625
20773
  createDecisionsClient: () => createDecisionsClient,
20626
20774
  createEmbeddingsClient: () => createEmbeddingsClient,
20627
20775
  createEventId: () => createEventId,
@@ -20695,6 +20843,7 @@ __export(src_exports, {
20695
20843
  normalizeDelegationChain: () => normalizeDelegationChain,
20696
20844
  normalizeNodeVerificationStatus: () => normalizeNodeVerificationStatus,
20697
20845
  normalizeNodeWriteInput: () => normalizeNodeWriteInput,
20846
+ normalizeResolvedInteractivePrincipal: () => normalizeResolvedInteractivePrincipal,
20698
20847
  normalizeRetentionDays: () => normalizeRetentionDays,
20699
20848
  normalizeTopicQuery: () => normalizeTopicQuery,
20700
20849
  normalizeWebhookPatterns: () => normalizeWebhookPatterns,
@@ -20784,14 +20933,14 @@ function requireString(value, reason, label) {
20784
20933
  }
20785
20934
  return normalized;
20786
20935
  }
20787
- function requirePrincipalType(principalType) {
20788
- if (!principalType) {
20936
+ function requirePrincipalType(principalType2) {
20937
+ if (!principalType2) {
20789
20938
  throw new LucernSdkAuthContextError(
20790
20939
  "principal_missing",
20791
20940
  "Canonical Lucern SDK auth context is missing principalType."
20792
20941
  );
20793
20942
  }
20794
- return principalType;
20943
+ return principalType2;
20795
20944
  }
20796
20945
  function requireAuthMode(authMode) {
20797
20946
  if (!authMode) {
@@ -20837,7 +20986,7 @@ function normalizeCanonicalLucernAuthContext(input) {
20837
20986
  );
20838
20987
  const roles = cleanStringList(input.roles);
20839
20988
  const scopes = cleanStringList(input.scopes);
20840
- const principalType = requirePrincipalType(input.principalType);
20989
+ const principalType2 = requirePrincipalType(input.principalType);
20841
20990
  const authMode = requireAuthMode(input.authMode);
20842
20991
  const roleBasedInteractiveAuth = authMode === "interactive_user" && roles.length > 0;
20843
20992
  if (roles.length === 0 || scopes.length === 0 && !roleBasedInteractiveAuth) {
@@ -20866,7 +21015,7 @@ function normalizeCanonicalLucernAuthContext(input) {
20866
21015
  principalId,
20867
21016
  tenantId,
20868
21017
  workspaceId,
20869
- principalType,
21018
+ principalType: principalType2,
20870
21019
  authMode,
20871
21020
  roles,
20872
21021
  scopes,
@@ -21855,6 +22004,128 @@ function listResultFromEnvelope(data, legacyKey) {
21855
22004
  );
21856
22005
  }
21857
22006
 
22007
+ // ../sdk/src/control-plane.ts
22008
+ var LucernControlPlaneIdentityError = class extends Error {
22009
+ reason;
22010
+ principalStatus;
22011
+ tenantStatus;
22012
+ workspaceStatus;
22013
+ details;
22014
+ constructor(failure) {
22015
+ super(failure.message);
22016
+ this.name = "LucernControlPlaneIdentityError";
22017
+ this.reason = failure.reason;
22018
+ this.principalStatus = failure.principalStatus;
22019
+ this.tenantStatus = failure.tenantStatus;
22020
+ this.workspaceStatus = failure.workspaceStatus;
22021
+ this.details = failure.details;
22022
+ }
22023
+ };
22024
+ function cleanString3(value) {
22025
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
22026
+ }
22027
+ function stringList(value) {
22028
+ if (!Array.isArray(value)) {
22029
+ return [];
22030
+ }
22031
+ return [
22032
+ ...new Set(
22033
+ value.filter((entry) => typeof entry === "string").map((entry) => entry.trim()).filter(Boolean)
22034
+ )
22035
+ ];
22036
+ }
22037
+ function principalType(value) {
22038
+ switch (value) {
22039
+ case "service":
22040
+ case "service_principal":
22041
+ return "service";
22042
+ case "agent":
22043
+ return "agent";
22044
+ case "group":
22045
+ return "group";
22046
+ case "external_viewer":
22047
+ case "external_stakeholder":
22048
+ return "external_viewer";
22049
+ default:
22050
+ return "human";
22051
+ }
22052
+ }
22053
+ function adminFlags(roles) {
22054
+ const normalized = roles.map((role) => role.toLowerCase());
22055
+ const isPlatformAdmin = normalized.includes("platform_admin");
22056
+ const isTenantAdmin = isPlatformAdmin || normalized.includes("tenant_admin");
22057
+ const isWorkspaceAdmin = isTenantAdmin || normalized.includes("workspace_admin") || normalized.includes("workspace_owner");
22058
+ return { isPlatformAdmin, isTenantAdmin, isWorkspaceAdmin };
22059
+ }
22060
+ function normalizeResolvedInteractivePrincipal(payload) {
22061
+ if ("ok" in payload && payload.ok === false) {
22062
+ throw new LucernControlPlaneIdentityError(payload);
22063
+ }
22064
+ const principalId = cleanString3(payload.principalId);
22065
+ const clerkId = cleanString3(payload.clerkId);
22066
+ const tenantId = cleanString3(payload.tenantId);
22067
+ if (!principalId || !clerkId || !tenantId) {
22068
+ throw new LucernControlPlaneIdentityError({
22069
+ ok: false,
22070
+ reason: "resolver_unavailable",
22071
+ message: "Control-plane principal resolver returned an incomplete principal context.",
22072
+ principalStatus: payload.principalStatus ?? "missing",
22073
+ tenantStatus: payload.tenantStatus,
22074
+ workspaceStatus: payload.workspaceStatus
22075
+ });
22076
+ }
22077
+ const roles = stringList(payload.roles);
22078
+ const scopes = stringList(payload.scopes);
22079
+ const workspaceId = cleanString3(payload.workspaceId) ?? null;
22080
+ const flags = adminFlags(roles);
22081
+ return {
22082
+ principalId,
22083
+ principalType: principalType(payload.principalType),
22084
+ clerkId,
22085
+ tenantId,
22086
+ workspaceId,
22087
+ roles,
22088
+ scopes,
22089
+ groupIds: stringList(payload.groupIds),
22090
+ permittedToolNames: stringList(payload.permittedToolNames),
22091
+ permittedPackKeys: stringList(payload.permittedPackKeys),
22092
+ principalStatus: cleanString3(payload.principalStatus) ?? "active",
22093
+ tenantStatus: cleanString3(payload.tenantStatus) ?? "active",
22094
+ workspaceStatus: cleanString3(payload.workspaceStatus) ?? (workspaceId ? "active" : "none"),
22095
+ isPlatformAdmin: typeof payload.isPlatformAdmin === "boolean" ? payload.isPlatformAdmin : flags.isPlatformAdmin,
22096
+ isTenantAdmin: typeof payload.isTenantAdmin === "boolean" ? payload.isTenantAdmin : flags.isTenantAdmin,
22097
+ isWorkspaceAdmin: typeof payload.isWorkspaceAdmin === "boolean" ? payload.isWorkspaceAdmin : flags.isWorkspaceAdmin,
22098
+ permit: {
22099
+ subject: cleanString3(payload.permit?.subject) ?? principalId,
22100
+ tenant: cleanString3(payload.permit?.tenant) ?? tenantId,
22101
+ ...workspaceId ? { workspace: cleanString3(payload.permit?.workspace) ?? workspaceId } : {}
22102
+ },
22103
+ authMode: "interactive_user",
22104
+ sessionId: payload.sessionId,
22105
+ delegatedBy: payload.delegatedBy,
22106
+ expiresAt: payload.expiresAt
22107
+ };
22108
+ }
22109
+ function createControlPlaneIdentityClient(config = {}) {
22110
+ const gateway = createGatewayRequestClient(config);
22111
+ return {
22112
+ async resolveInteractivePrincipal(input) {
22113
+ return gateway.request({
22114
+ path: "/api/platform/v1/control-plane/identity/resolve-interactive-principal",
22115
+ method: "POST",
22116
+ body: input
22117
+ }).then(
22118
+ (response) => mapGatewayData(response, normalizeResolvedInteractivePrincipal)
22119
+ );
22120
+ }
22121
+ };
22122
+ }
22123
+ function createControlPlaneClient(config = {}) {
22124
+ return {
22125
+ identity: createControlPlaneIdentityClient(config)
22126
+ };
22127
+ }
22128
+
21858
22129
  // ../sdk/src/identityClient.ts
21859
22130
  function createIdentityWhoamiClient(config = {}) {
21860
22131
  const gateway = createGatewayRequestClient(config);
@@ -21922,13 +22193,25 @@ function createIdentityClient(config = {}) {
21922
22193
  (response) => mapGatewayData(response, (data) => ({
21923
22194
  principalId: data.principalId,
21924
22195
  principalType: data.principalType,
22196
+ clerkId: data.clerkId,
21925
22197
  tenantId: data.tenantId ?? null,
21926
22198
  workspaceId: data.workspaceId ?? null,
21927
22199
  scopes: Array.isArray(data.scopes) ? data.scopes : [],
21928
22200
  roles: Array.isArray(data.roles) ? data.roles : [],
22201
+ groupIds: Array.isArray(data.groupIds) ? data.groupIds : [],
22202
+ permittedToolNames: Array.isArray(data.permittedToolNames) ? data.permittedToolNames : [],
22203
+ permittedPackKeys: Array.isArray(data.permittedPackKeys) ? data.permittedPackKeys : [],
22204
+ principalStatus: data.principalStatus,
22205
+ tenantStatus: data.tenantStatus,
22206
+ workspaceStatus: data.workspaceStatus,
21929
22207
  isPlatformAdmin: data.isPlatformAdmin === true,
21930
22208
  isTenantAdmin: data.isTenantAdmin === true,
21931
22209
  isWorkspaceAdmin: data.isWorkspaceAdmin === true,
22210
+ permit: data.permit ?? (data.tenantId ? {
22211
+ subject: data.principalId,
22212
+ tenant: data.tenantId,
22213
+ ...data.workspaceId ? { workspace: data.workspaceId } : {}
22214
+ } : void 0),
21932
22215
  authMode: data.authMode,
21933
22216
  sessionId: data.sessionId,
21934
22217
  delegatedBy: data.delegatedBy,
@@ -21936,6 +22219,19 @@ function createIdentityClient(config = {}) {
21936
22219
  }))
21937
22220
  );
21938
22221
  },
22222
+ /**
22223
+ * Resolve a Clerk subject through the tenant control-plane Permit projection.
22224
+ * @deprecated Prefer lucern.controlPlane.identity.resolveInteractivePrincipal().
22225
+ */
22226
+ async resolveInteractivePrincipal(input) {
22227
+ return gateway.request({
22228
+ path: "/api/platform/v1/control-plane/identity/resolve-interactive-principal",
22229
+ method: "POST",
22230
+ body: input
22231
+ }).then(
22232
+ (response) => mapGatewayData(response, normalizeResolvedInteractivePrincipal)
22233
+ );
22234
+ },
21939
22235
  /**
21940
22236
  * List principals in the current identity scope.
21941
22237
  */
@@ -22132,7 +22428,7 @@ var LucernAccessControlError = class extends LucernSdkAuthContextError {
22132
22428
  this.policyDecision = policyDecision;
22133
22429
  }
22134
22430
  };
22135
- function cleanString3(value) {
22431
+ function cleanString4(value) {
22136
22432
  const normalized = value?.trim();
22137
22433
  return normalized ? normalized : void 0;
22138
22434
  }
@@ -22147,7 +22443,7 @@ function cleanStringList2(values) {
22147
22443
  ];
22148
22444
  }
22149
22445
  function requireString2(value, reason, label) {
22150
- const normalized = cleanString3(value);
22446
+ const normalized = cleanString4(value);
22151
22447
  if (!normalized) {
22152
22448
  throw new LucernAccessControlError(
22153
22449
  reason,
@@ -22156,13 +22452,19 @@ function requireString2(value, reason, label) {
22156
22452
  }
22157
22453
  return normalized;
22158
22454
  }
22159
- function normalizePrincipalType(principalType) {
22160
- if (principalType === "agent") {
22455
+ function normalizePrincipalType(principalType2) {
22456
+ if (principalType2 === "agent") {
22161
22457
  return "agent";
22162
22458
  }
22163
- if (principalType === "service") {
22459
+ if (principalType2 === "service") {
22164
22460
  return "service";
22165
22461
  }
22462
+ if (principalType2 === "group") {
22463
+ return "group";
22464
+ }
22465
+ if (principalType2 === "external_viewer") {
22466
+ return "external_viewer";
22467
+ }
22166
22468
  return "human";
22167
22469
  }
22168
22470
  function aliasKey(alias) {
@@ -22171,15 +22473,15 @@ function aliasKey(alias) {
22171
22473
  function normalizeAliases(input, canonicalClerkUserId) {
22172
22474
  const aliases = /* @__PURE__ */ new Map();
22173
22475
  for (const alias of input ?? []) {
22174
- const externalSubjectId = cleanString3(alias.externalSubjectId);
22476
+ const externalSubjectId = cleanString4(alias.externalSubjectId);
22175
22477
  if (!externalSubjectId) {
22176
22478
  continue;
22177
22479
  }
22178
22480
  const normalized = {
22179
- provider: cleanString3(alias.provider) ?? "clerk",
22180
- providerProjectId: cleanString3(alias.providerProjectId),
22481
+ provider: cleanString4(alias.provider) ?? "clerk",
22482
+ providerProjectId: cleanString4(alias.providerProjectId),
22181
22483
  externalSubjectId,
22182
- status: cleanString3(alias.status)
22484
+ status: cleanString4(alias.status)
22183
22485
  };
22184
22486
  aliases.set(aliasKey(normalized), normalized);
22185
22487
  }
@@ -22224,10 +22526,10 @@ function normalizeCanonicalPrincipalIdentity(input, options = {}) {
22224
22526
  "principal_missing",
22225
22527
  "principalId"
22226
22528
  );
22227
- const principalType = normalizePrincipalType(principalInput.principalType);
22228
- const observedClerkId = cleanString3(options.observedClerkId);
22229
- const canonicalClerkUserId = cleanString3(principalInput.canonicalClerkUserId) ?? cleanString3(principalInput.clerkId);
22230
- if (principalType === "human" && !canonicalClerkUserId) {
22529
+ const principalType2 = normalizePrincipalType(principalInput.principalType);
22530
+ const observedClerkId = cleanString4(options.observedClerkId);
22531
+ const canonicalClerkUserId = cleanString4(principalInput.canonicalClerkUserId) ?? cleanString4(principalInput.clerkId);
22532
+ if (principalType2 === "human" && !canonicalClerkUserId) {
22231
22533
  throw new LucernAccessControlError(
22232
22534
  "clerk_alias_missing",
22233
22535
  "Human principals require one canonical Clerk user id."
@@ -22249,11 +22551,11 @@ function normalizeCanonicalPrincipalIdentity(input, options = {}) {
22249
22551
  }
22250
22552
  return {
22251
22553
  principalId,
22252
- principalType,
22554
+ principalType: principalType2,
22253
22555
  canonicalClerkUserId,
22254
22556
  clerkIdentityAliases: aliases,
22255
- tenantId: cleanString3(principalInput.tenantId),
22256
- workspaceId: cleanString3(principalInput.workspaceId),
22557
+ tenantId: cleanString4(principalInput.tenantId),
22558
+ workspaceId: cleanString4(principalInput.workspaceId),
22257
22559
  roles: cleanStringList2(principalInput.roles),
22258
22560
  scopes: cleanStringList2(principalInput.scopes)
22259
22561
  };
@@ -22278,7 +22580,7 @@ function buildPolicyInput(identity, input) {
22278
22580
  "tenant_missing",
22279
22581
  "tenantId"
22280
22582
  );
22281
- const workspaceId = cleanString3(input.workspaceId ?? identity.workspaceId);
22583
+ const workspaceId = cleanString4(input.workspaceId ?? identity.workspaceId);
22282
22584
  if (resourceRequiresWorkspace(input.resource) && !workspaceId) {
22283
22585
  throw new LucernAccessControlError(
22284
22586
  "workspace_missing",
@@ -23678,12 +23980,12 @@ function createGraphClient(config = {}) {
23678
23980
  }
23679
23981
 
23680
23982
  // ../sdk/src/topicsClient.ts
23681
- function cleanString4(value) {
23983
+ function cleanString5(value) {
23682
23984
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
23683
23985
  }
23684
23986
  function normalizeTopicRecord(value) {
23685
23987
  const record = asRecord(value);
23686
- const topicId = cleanString4(record.topicId) ?? cleanString4(record.id) ?? cleanString4(record._id);
23988
+ const topicId = cleanString5(record.topicId) ?? cleanString5(record.id) ?? cleanString5(record._id);
23687
23989
  return withTopicAlias({
23688
23990
  ...record,
23689
23991
  ...topicId ? { topicId } : {}
@@ -24896,7 +25198,7 @@ function createEmbeddingsClient(config = {}) {
24896
25198
  }
24897
25199
 
24898
25200
  // ../sdk/src/contextClient.ts
24899
- function cleanString5(value) {
25201
+ function cleanString6(value) {
24900
25202
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
24901
25203
  }
24902
25204
  function cleanNumber(value) {
@@ -24908,11 +25210,11 @@ function cleanBoolean(value) {
24908
25210
  function buildCompileContextRequest(topicIdOrInput = {}, input = {}) {
24909
25211
  const effectiveInput = typeof topicIdOrInput === "string" ? input : topicIdOrInput;
24910
25212
  const payload = {};
24911
- const topicId = typeof topicIdOrInput === "string" ? cleanString5(topicIdOrInput) : cleanString5(effectiveInput.topicId);
25213
+ const topicId = typeof topicIdOrInput === "string" ? cleanString6(topicIdOrInput) : cleanString6(effectiveInput.topicId);
24912
25214
  if (topicId) {
24913
25215
  payload.topicId = topicId;
24914
25216
  }
24915
- const query5 = cleanString5(effectiveInput.query);
25217
+ const query5 = cleanString6(effectiveInput.query);
24916
25218
  if (query5) {
24917
25219
  payload.query = query5;
24918
25220
  }
@@ -24920,7 +25222,7 @@ function buildCompileContextRequest(topicIdOrInput = {}, input = {}) {
24920
25222
  if (budget !== void 0) {
24921
25223
  payload.budget = budget;
24922
25224
  }
24923
- const ranking = cleanString5(effectiveInput.ranking) ?? cleanString5(effectiveInput.rankingProfile);
25225
+ const ranking = cleanString6(effectiveInput.ranking) ?? cleanString6(effectiveInput.rankingProfile);
24924
25226
  if (ranking) {
24925
25227
  payload.ranking = ranking;
24926
25228
  }
@@ -24936,7 +25238,7 @@ function buildCompileContextRequest(topicIdOrInput = {}, input = {}) {
24936
25238
  if (includeEntities !== void 0) {
24937
25239
  payload.includeEntities = includeEntities;
24938
25240
  }
24939
- const mode = cleanString5(effectiveInput.mode);
25241
+ const mode = cleanString6(effectiveInput.mode);
24940
25242
  if (mode) {
24941
25243
  payload.mode = mode;
24942
25244
  }
@@ -24944,11 +25246,11 @@ function buildCompileContextRequest(topicIdOrInput = {}, input = {}) {
24944
25246
  if (includeFailures !== void 0) {
24945
25247
  payload.includeFailures = includeFailures;
24946
25248
  }
24947
- const worktreeId = cleanString5(effectiveInput.worktreeId);
25249
+ const worktreeId = cleanString6(effectiveInput.worktreeId);
24948
25250
  if (worktreeId) {
24949
25251
  payload.worktreeId = worktreeId;
24950
25252
  }
24951
- const sessionId = cleanString5(effectiveInput.sessionId);
25253
+ const sessionId = cleanString6(effectiveInput.sessionId);
24952
25254
  if (sessionId) {
24953
25255
  payload.sessionId = sessionId;
24954
25256
  }
@@ -25957,6 +26259,7 @@ var FUNCTION_SURFACE_METHOD_PATHS = [
25957
26259
  "contracts.evaluateContract",
25958
26260
  "contracts.getContractStatus",
25959
26261
  "contradictions.flagContradiction",
26262
+ "controlPlane.identity.resolveInteractivePrincipal",
25960
26263
  "coordination.broadcastMessage",
25961
26264
  "coordination.claimFiles",
25962
26265
  "coordination.endSession",
@@ -26162,6 +26465,7 @@ var CONTRACTS = {
26162
26465
  "remove_edges_between": { method: "DELETE", path: "/edges/between", kind: "mutation", idempotent: true, surfaceIntent: "mcp_analysis" },
26163
26466
  "remove_lens_from_topic": { method: "DELETE", path: "/lenses/apply", kind: "mutation", idempotent: true, surfaceIntent: "mcp_workflow" },
26164
26467
  "resolve_effective_ontology": { method: "POST", path: "/ontologies/effective", kind: "query", idempotent: false, surfaceIntent: "mcp_workflow" },
26468
+ "resolve_interactive_principal": { method: "POST", path: "/control-plane/identity/resolve-interactive-principal", kind: "query", idempotent: false, surfaceIntent: "mcp_core" },
26165
26469
  "run_graph_intelligence_query": { method: "POST", path: "/graph-intelligence/run", kind: "query", idempotent: false, surfaceIntent: "mcp_analysis" },
26166
26470
  "search_beliefs": { method: "POST", path: "/beliefs/search", kind: "query", idempotent: false, surfaceIntent: "mcp_core" },
26167
26471
  "search_evidence": { method: "POST", path: "/evidence/search", kind: "query", idempotent: false, surfaceIntent: "mcp_core" },
@@ -26544,6 +26848,9 @@ function createFunctionSurfaceClient(config = {}) {
26544
26848
  resolveEffectiveOntology(input = {}, idempotencyKey) {
26545
26849
  return execute("resolve_effective_ontology", input, idempotencyKey);
26546
26850
  },
26851
+ resolveInteractivePrincipal(input = {}, idempotencyKey) {
26852
+ return execute("resolve_interactive_principal", input, idempotencyKey);
26853
+ },
26547
26854
  runGraphIntelligenceQuery(input = {}, idempotencyKey) {
26548
26855
  return execute("run_graph_intelligence_query", input, idempotencyKey);
26549
26856
  },
@@ -26804,7 +27111,7 @@ var ORG_GRAPH_SEARCH_FIELDS = [
26804
27111
  "cursor",
26805
27112
  "provenanceScope"
26806
27113
  ];
26807
- function cleanString6(value, label) {
27114
+ function cleanString7(value, label) {
26808
27115
  const normalized = value?.trim();
26809
27116
  if (!normalized) {
26810
27117
  throw new Error(`${label} is required`);
@@ -26826,9 +27133,9 @@ function searchBody(input) {
26826
27133
  "orgGraphSearch.search"
26827
27134
  );
26828
27135
  return {
26829
- tenantId: cleanString6(input.tenantId, "tenantId"),
26830
- workspaceId: cleanString6(input.workspaceId, "workspaceId"),
26831
- query: cleanString6(input.query, "query"),
27136
+ tenantId: cleanString7(input.tenantId, "tenantId"),
27137
+ workspaceId: cleanString7(input.workspaceId, "workspaceId"),
27138
+ query: cleanString7(input.query, "query"),
26832
27139
  nodeTypes: input.nodeTypes,
26833
27140
  minConfidence: input.minConfidence,
26834
27141
  limit: input.limit,
@@ -26838,8 +27145,8 @@ function searchBody(input) {
26838
27145
  }
26839
27146
  function listQuery2(input) {
26840
27147
  return {
26841
- tenantId: cleanString6(input.tenantId, "tenantId"),
26842
- workspaceId: cleanString6(input.workspaceId, "workspaceId"),
27148
+ tenantId: cleanString7(input.tenantId, "tenantId"),
27149
+ workspaceId: cleanString7(input.workspaceId, "workspaceId"),
26843
27150
  nodeTypes: input.nodeTypes?.join(","),
26844
27151
  minConfidence: input.minConfidence,
26845
27152
  limit: input.limit,
@@ -26873,8 +27180,8 @@ function createOrgGraphSearchClient(config = {}) {
26873
27180
  return gateway.request({
26874
27181
  path: `/api/platform/v1/org-graph-search/nodes/${nodePath}${toQueryString(
26875
27182
  {
26876
- tenantId: cleanString6(input.tenantId, "tenantId"),
26877
- workspaceId: cleanString6(input.workspaceId, "workspaceId"),
27183
+ tenantId: cleanString7(input.tenantId, "tenantId"),
27184
+ workspaceId: cleanString7(input.workspaceId, "workspaceId"),
26878
27185
  globalId: nodeId ? void 0 : globalId
26879
27186
  }
26880
27187
  )}`
@@ -27839,7 +28146,7 @@ function createToolRegistryClient(config = {}) {
27839
28146
  }
27840
28147
 
27841
28148
  // ../sdk/src/version.ts
27842
- var LUCERN_SDK_VERSION = "0.3.0-alpha.12";
28149
+ var LUCERN_SDK_VERSION = "0.3.0-alpha.14";
27843
28150
 
27844
28151
  // ../sdk/src/workflowClient.ts
27845
28152
  function normalizeLensQuery(value) {
@@ -28316,6 +28623,7 @@ function createLucernClient(config = {}) {
28316
28623
  const ontologyLinksClient = createOntologyLinksClient(gatewayConfig);
28317
28624
  const orgGraphSearchClient = createOrgGraphSearchClient(gatewayConfig);
28318
28625
  const functionSurfaceClient = createFunctionSurfaceClient(gatewayConfig);
28626
+ const controlPlaneClient = createControlPlaneClient(gatewayConfig);
28319
28627
  const toolRegistryClient = createToolRegistryClient(gatewayConfig);
28320
28628
  const modelRuntimeClient = createModelRuntimeClient(gatewayConfig);
28321
28629
  const packsClient = createPacksClient(gatewayConfig);
@@ -29979,9 +30287,16 @@ function createLucernClient(config = {}) {
29979
30287
  disable: packsClient.disable
29980
30288
  },
29981
30289
  nodes: nodesNamespace,
30290
+ controlPlane: {
30291
+ identity: {
30292
+ resolveInteractivePrincipal: controlPlaneClient.identity.resolveInteractivePrincipal
30293
+ },
30294
+ raw: controlPlaneClient
30295
+ },
29982
30296
  identity: {
29983
30297
  ...identityFacade,
29984
30298
  access: accessControlClient,
30299
+ resolveInteractivePrincipal: identityClient.resolveInteractivePrincipal,
29985
30300
  evaluatePolicy: identityClient.evaluatePolicy,
29986
30301
  recordPolicyDecision: identityClient.recordPolicyDecision,
29987
30302
  putSecretReference: identityClient.putSecretReference,
@@ -30026,6 +30341,7 @@ function createLucernClient(config = {}) {
30026
30341
  ontologyLinks: ontologyLinksClient,
30027
30342
  orgGraphSearch: orgGraphSearchClient,
30028
30343
  functionSurface: functionSurfaceClient,
30344
+ controlPlane: controlPlaneClient,
30029
30345
  toolRegistry: toolRegistryClient,
30030
30346
  modelRuntime: modelRuntimeClient,
30031
30347
  packs: packsClient,
@@ -30043,7 +30359,7 @@ function createLucernClient(config = {}) {
30043
30359
  }
30044
30360
 
30045
30361
  // ../sdk/src/facade/context.ts
30046
- function cleanString7(value) {
30362
+ function cleanString8(value) {
30047
30363
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
30048
30364
  }
30049
30365
  function cleanNumber2(value) {
@@ -30055,11 +30371,11 @@ function cleanBoolean2(value) {
30055
30371
  function buildCompileContextRequest2(topicIdOrInput = {}, input = {}) {
30056
30372
  const effectiveInput = typeof topicIdOrInput === "string" ? input : topicIdOrInput;
30057
30373
  const payload = {};
30058
- const topicId = typeof topicIdOrInput === "string" ? cleanString7(topicIdOrInput) : cleanString7(effectiveInput.topicId);
30374
+ const topicId = typeof topicIdOrInput === "string" ? cleanString8(topicIdOrInput) : cleanString8(effectiveInput.topicId);
30059
30375
  if (topicId) {
30060
30376
  payload.topicId = topicId;
30061
30377
  }
30062
- const query5 = cleanString7(effectiveInput.query);
30378
+ const query5 = cleanString8(effectiveInput.query);
30063
30379
  if (query5) {
30064
30380
  payload.query = query5;
30065
30381
  }
@@ -30067,7 +30383,7 @@ function buildCompileContextRequest2(topicIdOrInput = {}, input = {}) {
30067
30383
  if (budget !== void 0) {
30068
30384
  payload.budget = budget;
30069
30385
  }
30070
- const ranking = cleanString7(effectiveInput.ranking) ?? cleanString7(effectiveInput.rankingProfile);
30386
+ const ranking = cleanString8(effectiveInput.ranking) ?? cleanString8(effectiveInput.rankingProfile);
30071
30387
  if (ranking) {
30072
30388
  payload.ranking = ranking;
30073
30389
  }
@@ -30083,7 +30399,7 @@ function buildCompileContextRequest2(topicIdOrInput = {}, input = {}) {
30083
30399
  if (includeEntities !== void 0) {
30084
30400
  payload.includeEntities = includeEntities;
30085
30401
  }
30086
- const mode = cleanString7(effectiveInput.mode);
30402
+ const mode = cleanString8(effectiveInput.mode);
30087
30403
  if (mode) {
30088
30404
  payload.mode = mode;
30089
30405
  }
@@ -30091,11 +30407,11 @@ function buildCompileContextRequest2(topicIdOrInput = {}, input = {}) {
30091
30407
  if (includeFailures !== void 0) {
30092
30408
  payload.includeFailures = includeFailures;
30093
30409
  }
30094
- const worktreeId = cleanString7(effectiveInput.worktreeId);
30410
+ const worktreeId = cleanString8(effectiveInput.worktreeId);
30095
30411
  if (worktreeId) {
30096
30412
  payload.worktreeId = worktreeId;
30097
30413
  }
30098
- const sessionId = cleanString7(effectiveInput.sessionId);
30414
+ const sessionId = cleanString8(effectiveInput.sessionId);
30099
30415
  if (sessionId) {
30100
30416
  payload.sessionId = sessionId;
30101
30417
  }
@@ -31517,7 +31833,13 @@ var SESSION_AUTH_MODES = [
31517
31833
  "tenant_api_key",
31518
31834
  "session_token"
31519
31835
  ];
31520
- var SESSION_PRINCIPAL_TYPES = ["human", "service", "agent"];
31836
+ var SESSION_PRINCIPAL_TYPES = [
31837
+ "human",
31838
+ "service",
31839
+ "agent",
31840
+ "group",
31841
+ "external_viewer"
31842
+ ];
31521
31843
  var SESSION_LIFECYCLE_STATUSES = [
31522
31844
  "active",
31523
31845
  "expired",
@@ -31530,6 +31852,12 @@ function inferSessionPrincipalType(principalId) {
31530
31852
  if (principalId.startsWith("agent:")) {
31531
31853
  return "agent";
31532
31854
  }
31855
+ if (principalId.startsWith("group:")) {
31856
+ return "group";
31857
+ }
31858
+ if (principalId.startsWith("external:") || principalId.startsWith("external_viewer:")) {
31859
+ return "external_viewer";
31860
+ }
31533
31861
  return "service";
31534
31862
  }
31535
31863
  function normalizeDelegationChain(args) {
@@ -34645,7 +34973,7 @@ function createLucernStandaloneMcpServer(options) {
34645
34973
  });
34646
34974
  const server = new McpServer({
34647
34975
  name: "lucern-mcp",
34648
- version: "0.3.0-alpha.12"
34976
+ version: "0.3.0-alpha.14"
34649
34977
  });
34650
34978
  registerTools(server, runtime);
34651
34979
  const resources = registerResources(server, runtime, observationStore);