@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/cli.js CHANGED
@@ -1421,6 +1421,35 @@ defineTable({
1421
1421
  { kind: "index", name: "by_source", columns: ["source"] }
1422
1422
  ]
1423
1423
  });
1424
+ defineTable({
1425
+ name: "domainEvents",
1426
+ component: "kernel",
1427
+ category: "events",
1428
+ shape: z.object({
1429
+ "eventId": z.string(),
1430
+ "type": z.string(),
1431
+ "version": z.string(),
1432
+ "timestamp": z.number(),
1433
+ "tenantId": z.string().optional(),
1434
+ "workspaceId": z.string().optional(),
1435
+ "topicId": z.string(),
1436
+ "resourceId": z.string(),
1437
+ "resourceType": z.string(),
1438
+ "actorId": z.string(),
1439
+ "actorType": z.enum(["human", "agent", "service"]),
1440
+ "data": z.record(z.any()),
1441
+ "correlationId": z.string().optional(),
1442
+ "expiresAt": z.number()
1443
+ }),
1444
+ indices: [
1445
+ { kind: "index", name: "by_eventId", columns: ["eventId"] },
1446
+ { kind: "index", name: "by_topic_timestamp", columns: ["topicId", "timestamp"] },
1447
+ { kind: "index", name: "by_tenant_workspace_timestamp", columns: ["tenantId", "workspaceId", "timestamp"] },
1448
+ { kind: "index", name: "by_type_timestamp", columns: ["type", "timestamp"] },
1449
+ { kind: "index", name: "by_resource", columns: ["resourceType", "resourceId", "timestamp"] },
1450
+ { kind: "index", name: "by_expiresAt", columns: ["expiresAt"] }
1451
+ ]
1452
+ });
1424
1453
  defineTable({
1425
1454
  name: "beliefConfidence",
1426
1455
  component: "kernel",
@@ -4827,7 +4856,10 @@ defineTable({
4827
4856
  }),
4828
4857
  indices: [
4829
4858
  { kind: "index", name: "by_principalId", columns: ["principalId"] },
4859
+ { kind: "index", name: "by_provider_subject", columns: ["provider", "providerSubjectId"] },
4860
+ { kind: "index", name: "by_provider_project_subject", columns: ["provider", "providerProjectId", "providerSubjectId"] },
4830
4861
  { kind: "index", name: "by_tenant_provider_subject", columns: ["tenantId", "provider", "providerSubjectId"] },
4862
+ { kind: "index", name: "by_tenant_provider_project_subject", columns: ["tenantId", "provider", "providerProjectId", "providerSubjectId"] },
4831
4863
  {
4832
4864
  kind: "index",
4833
4865
  name: "by_tenant_provider_alias",
@@ -8195,6 +8227,40 @@ var GENERATED_INFISICAL_RUNTIME_ENV = {
8195
8227
  ],
8196
8228
  "description": "Canonical Lucern API gateway URL. Canonical Lucern API gateway base URL. Older names remain aliases only."
8197
8229
  },
8230
+ {
8231
+ "secretId": "platform.clerk.webhook-secret",
8232
+ "canonicalName": "LUCERN_CLERK_WEBHOOK_SECRET",
8233
+ "envNames": [
8234
+ "CLERK_WEBHOOK_SECRET",
8235
+ "CLERK_WEBHOOK_SIGNING_SECRET",
8236
+ "LUCERN_CLERK_WEBHOOK_SECRET"
8237
+ ],
8238
+ "aliases": [
8239
+ "CLERK_WEBHOOK_SECRET",
8240
+ "CLERK_WEBHOOK_SIGNING_SECRET"
8241
+ ],
8242
+ "writeNames": [
8243
+ "LUCERN_CLERK_WEBHOOK_SECRET"
8244
+ ],
8245
+ "required": true,
8246
+ "secret": true,
8247
+ "public": false,
8248
+ "sourcePath": "/platform/auth",
8249
+ "environmentPolicy": "environment_specific",
8250
+ "consumers": [
8251
+ "lucern-gateway"
8252
+ ],
8253
+ "destinations": [
8254
+ {
8255
+ "kind": "vercel",
8256
+ "target": "lucern-gateway",
8257
+ "writeNames": [
8258
+ "LUCERN_CLERK_WEBHOOK_SECRET"
8259
+ ]
8260
+ }
8261
+ ],
8262
+ "description": "Lucern-owned Clerk/Svix webhook signing secret used by the gateway to verify Clerk identity and organization events before projecting them into Permit."
8263
+ },
8198
8264
  {
8199
8265
  "canonicalName": "LUCERN_CLI_SESSION_TTL_MS",
8200
8266
  "envNames": [
@@ -12654,7 +12720,7 @@ var IDENTITY_WHOAMI = {
12654
12720
  description: "Canonical identity summary for the current session",
12655
12721
  fields: {
12656
12722
  principalId: "string \u2014 canonical federated principal identifier",
12657
- principalType: "string \u2014 human, service, or agent",
12723
+ principalType: "string \u2014 human, service, agent, group, or external_viewer",
12658
12724
  tenantId: "string | undefined \u2014 resolved tenant scope",
12659
12725
  workspaceId: "string | undefined \u2014 resolved workspace scope",
12660
12726
  scopes: "string[] | undefined \u2014 granted scopes for this session",
@@ -12665,6 +12731,49 @@ var IDENTITY_WHOAMI = {
12665
12731
  ontologyPrimitive: "identity",
12666
12732
  tier: "workhorse"
12667
12733
  };
12734
+ var RESOLVE_INTERACTIVE_PRINCIPAL = {
12735
+ name: "resolve_interactive_principal",
12736
+ 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.",
12737
+ parameters: {
12738
+ clerkId: {
12739
+ type: "string",
12740
+ description: "Authenticated Clerk subject (`sub`). Clerk proves identity only; it is not the authorization record."
12741
+ },
12742
+ tenantId: {
12743
+ type: "string",
12744
+ description: "Optional tenant scope. Omit only when the Clerk alias is globally unambiguous."
12745
+ },
12746
+ workspaceId: {
12747
+ type: "string",
12748
+ description: "Optional workspace scope. Required when the principal has access to multiple workspaces and no default can be inferred."
12749
+ },
12750
+ providerProjectId: {
12751
+ type: "string",
12752
+ description: "Optional Clerk project or provider instance id for tenants with multiple identity providers."
12753
+ }
12754
+ },
12755
+ required: ["clerkId"],
12756
+ response: {
12757
+ description: "Permit-backed Lucern principal context for tenant SDK bootstrap",
12758
+ fields: {
12759
+ principalId: "string \u2014 canonical Lucern principal identifier",
12760
+ principalType: "string \u2014 human, service, agent, group, or external_viewer",
12761
+ clerkId: "string \u2014 authenticated Clerk subject alias",
12762
+ tenantId: "string \u2014 resolved tenant scope",
12763
+ workspaceId: "string | null \u2014 resolved workspace scope",
12764
+ roles: "string[] \u2014 effective Permit roles",
12765
+ scopes: "string[] \u2014 effective scopes derived from Permit/control-plane projection",
12766
+ groupIds: "string[] \u2014 active Permit group memberships",
12767
+ principalStatus: "string \u2014 active, invited, suspended, disabled, revoked, or missing",
12768
+ tenantStatus: "string \u2014 projected tenant resource status",
12769
+ workspaceStatus: "string \u2014 projected workspace resource status",
12770
+ permit: "object \u2014 Permit subject, tenant, and optional workspace tuple"
12771
+ }
12772
+ },
12773
+ ownerModule: "control-plane",
12774
+ ontologyPrimitive: "identity",
12775
+ tier: "workhorse"
12776
+ };
12668
12777
  var COMPILE_CONTEXT = {
12669
12778
  name: "compile_context",
12670
12779
  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.",
@@ -14567,6 +14676,7 @@ var MCP_TOOL_CONTRACTS = {
14567
14676
  update_worktree_targets: UPDATE_WORKTREE_TARGETS,
14568
14677
  update_worktree_metadata: UPDATE_WORKTREE_METADATA,
14569
14678
  identity_whoami: IDENTITY_WHOAMI,
14679
+ resolve_interactive_principal: RESOLVE_INTERACTIVE_PRINCIPAL,
14570
14680
  compile_context: COMPILE_CONTEXT,
14571
14681
  record_scope_learning: RECORD_SCOPE_LEARNING,
14572
14682
  pipeline_snapshot: PIPELINE_SNAPSHOT,
@@ -14696,6 +14806,7 @@ function entries(names, surfaceClass, surfaceIntent, surfaces, rationale) {
14696
14806
  var MCP_CORE_OPERATION_NAMES = [
14697
14807
  "compile_context",
14698
14808
  "identity_whoami",
14809
+ "resolve_interactive_principal",
14699
14810
  "check_permission",
14700
14811
  "filter_by_permission",
14701
14812
  "create_belief",
@@ -15249,7 +15360,13 @@ function surfaceContract(args) {
15249
15360
  scopes: args.scopes ?? [
15250
15361
  args.kind === "query" ? `${args.domain}.read` : `${args.domain}.write`
15251
15362
  ],
15252
- allowedPrincipalTypes: ["user", "service", "agent"]
15363
+ allowedPrincipalTypes: [
15364
+ "user",
15365
+ "service",
15366
+ "agent",
15367
+ "group",
15368
+ "external_viewer"
15369
+ ]
15253
15370
  },
15254
15371
  convex: args.convex,
15255
15372
  gateway: args.gateway,
@@ -15391,8 +15508,6 @@ var contextContracts = [
15391
15508
  args: observationContextArgs
15392
15509
  })
15393
15510
  ];
15394
-
15395
- // ../contracts/src/function-registry/identity.ts
15396
15511
  var withPrincipal = (input, context) => ({
15397
15512
  ...input,
15398
15513
  tenantId: input.tenantId ?? context.tenantId,
@@ -15418,6 +15533,28 @@ var identityContracts = [
15418
15533
  inputProjection: withPrincipal
15419
15534
  }
15420
15535
  }),
15536
+ surfaceContract({
15537
+ name: "resolve_interactive_principal",
15538
+ kind: "query",
15539
+ domain: "controlPlane",
15540
+ surfaceClass: "platform_public",
15541
+ method: "POST",
15542
+ path: "/control-plane/identity/resolve-interactive-principal",
15543
+ sdkNamespace: "controlPlane.identity",
15544
+ sdkMethod: "resolveInteractivePrincipal",
15545
+ summary: "Resolve an authenticated Clerk user into a Permit-backed Lucern principal context.",
15546
+ args: z.object({
15547
+ clerkId: z.string().min(1),
15548
+ tenantId: z.string().min(1).optional(),
15549
+ workspaceId: z.string().min(1).optional(),
15550
+ providerProjectId: z.string().min(1).optional()
15551
+ }),
15552
+ convex: {
15553
+ module: "identity",
15554
+ functionName: "resolveInteractivePrincipal",
15555
+ kind: "query"
15556
+ }
15557
+ }),
15421
15558
  surfaceContract({
15422
15559
  name: "check_permission",
15423
15560
  kind: "query",
@@ -19222,6 +19359,13 @@ var TENANT_BOOTSTRAP_TABLE_REQUIREMENTS = [
19222
19359
  copyMode: "none",
19223
19360
  description: "Deliberation sessions are created by tenant workflows."
19224
19361
  },
19362
+ {
19363
+ component: "kernel",
19364
+ table: "domainEvents",
19365
+ prepopulation: "runtime_log",
19366
+ copyMode: "none",
19367
+ description: "Domain event rows are append-only runtime audit/exhaust data."
19368
+ },
19225
19369
  {
19226
19370
  component: "kernel",
19227
19371
  table: "epistemicAudit",
@@ -20401,6 +20545,7 @@ __export(src_exports, {
20401
20545
  LUCERN_SDK_VERSION: () => LUCERN_SDK_VERSION,
20402
20546
  LucernAccessControlError: () => LucernAccessControlError,
20403
20547
  LucernApiError: () => LucernApiError,
20548
+ LucernControlPlaneIdentityError: () => LucernControlPlaneIdentityError,
20404
20549
  LucernSdkAuthContextError: () => LucernSdkAuthContextError,
20405
20550
  MANAGE_WRITE_POLICY: () => MANAGE_WRITE_POLICY,
20406
20551
  MATCH_ENTITY_TYPE: () => MATCH_ENTITY_TYPE,
@@ -20432,6 +20577,7 @@ __export(src_exports, {
20432
20577
  REMOVE_EDGES_BETWEEN: () => REMOVE_EDGES_BETWEEN,
20433
20578
  REMOVE_LENS_FROM_TOPIC: () => REMOVE_LENS_FROM_TOPIC,
20434
20579
  RESOLVE_EFFECTIVE_ONTOLOGY: () => RESOLVE_EFFECTIVE_ONTOLOGY,
20580
+ RESOLVE_INTERACTIVE_PRINCIPAL: () => RESOLVE_INTERACTIVE_PRINCIPAL,
20435
20581
  RUN_GRAPH_INTELLIGENCE_QUERY: () => RUN_GRAPH_INTELLIGENCE_QUERY,
20436
20582
  SEARCH_BELIEFS: () => SEARCH_BELIEFS,
20437
20583
  SEARCH_EVIDENCE: () => SEARCH_EVIDENCE,
@@ -20497,6 +20643,8 @@ __export(src_exports, {
20497
20643
  createCanonicalAuthHeaders: () => createCanonicalAuthHeaders,
20498
20644
  createContextClient: () => createContextClient,
20499
20645
  createContextFacade: () => createContextFacade,
20646
+ createControlPlaneClient: () => createControlPlaneClient,
20647
+ createControlPlaneIdentityClient: () => createControlPlaneIdentityClient,
20500
20648
  createDecisionsClient: () => createDecisionsClient,
20501
20649
  createEmbeddingsClient: () => createEmbeddingsClient,
20502
20650
  createEventId: () => createEventId,
@@ -20570,6 +20718,7 @@ __export(src_exports, {
20570
20718
  normalizeDelegationChain: () => normalizeDelegationChain,
20571
20719
  normalizeNodeVerificationStatus: () => normalizeNodeVerificationStatus,
20572
20720
  normalizeNodeWriteInput: () => normalizeNodeWriteInput,
20721
+ normalizeResolvedInteractivePrincipal: () => normalizeResolvedInteractivePrincipal,
20573
20722
  normalizeRetentionDays: () => normalizeRetentionDays,
20574
20723
  normalizeTopicQuery: () => normalizeTopicQuery,
20575
20724
  normalizeWebhookPatterns: () => normalizeWebhookPatterns,
@@ -20659,14 +20808,14 @@ function requireString(value, reason, label) {
20659
20808
  }
20660
20809
  return normalized;
20661
20810
  }
20662
- function requirePrincipalType(principalType) {
20663
- if (!principalType) {
20811
+ function requirePrincipalType(principalType2) {
20812
+ if (!principalType2) {
20664
20813
  throw new LucernSdkAuthContextError(
20665
20814
  "principal_missing",
20666
20815
  "Canonical Lucern SDK auth context is missing principalType."
20667
20816
  );
20668
20817
  }
20669
- return principalType;
20818
+ return principalType2;
20670
20819
  }
20671
20820
  function requireAuthMode(authMode) {
20672
20821
  if (!authMode) {
@@ -20712,7 +20861,7 @@ function normalizeCanonicalLucernAuthContext(input) {
20712
20861
  );
20713
20862
  const roles = cleanStringList(input.roles);
20714
20863
  const scopes = cleanStringList(input.scopes);
20715
- const principalType = requirePrincipalType(input.principalType);
20864
+ const principalType2 = requirePrincipalType(input.principalType);
20716
20865
  const authMode = requireAuthMode(input.authMode);
20717
20866
  const roleBasedInteractiveAuth = authMode === "interactive_user" && roles.length > 0;
20718
20867
  if (roles.length === 0 || scopes.length === 0 && !roleBasedInteractiveAuth) {
@@ -20741,7 +20890,7 @@ function normalizeCanonicalLucernAuthContext(input) {
20741
20890
  principalId,
20742
20891
  tenantId,
20743
20892
  workspaceId,
20744
- principalType,
20893
+ principalType: principalType2,
20745
20894
  authMode,
20746
20895
  roles,
20747
20896
  scopes,
@@ -21730,6 +21879,128 @@ function listResultFromEnvelope(data, legacyKey) {
21730
21879
  );
21731
21880
  }
21732
21881
 
21882
+ // ../sdk/src/control-plane.ts
21883
+ var LucernControlPlaneIdentityError = class extends Error {
21884
+ reason;
21885
+ principalStatus;
21886
+ tenantStatus;
21887
+ workspaceStatus;
21888
+ details;
21889
+ constructor(failure) {
21890
+ super(failure.message);
21891
+ this.name = "LucernControlPlaneIdentityError";
21892
+ this.reason = failure.reason;
21893
+ this.principalStatus = failure.principalStatus;
21894
+ this.tenantStatus = failure.tenantStatus;
21895
+ this.workspaceStatus = failure.workspaceStatus;
21896
+ this.details = failure.details;
21897
+ }
21898
+ };
21899
+ function cleanString3(value) {
21900
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
21901
+ }
21902
+ function stringList(value) {
21903
+ if (!Array.isArray(value)) {
21904
+ return [];
21905
+ }
21906
+ return [
21907
+ ...new Set(
21908
+ value.filter((entry) => typeof entry === "string").map((entry) => entry.trim()).filter(Boolean)
21909
+ )
21910
+ ];
21911
+ }
21912
+ function principalType(value) {
21913
+ switch (value) {
21914
+ case "service":
21915
+ case "service_principal":
21916
+ return "service";
21917
+ case "agent":
21918
+ return "agent";
21919
+ case "group":
21920
+ return "group";
21921
+ case "external_viewer":
21922
+ case "external_stakeholder":
21923
+ return "external_viewer";
21924
+ default:
21925
+ return "human";
21926
+ }
21927
+ }
21928
+ function adminFlags(roles) {
21929
+ const normalized = roles.map((role) => role.toLowerCase());
21930
+ const isPlatformAdmin = normalized.includes("platform_admin");
21931
+ const isTenantAdmin = isPlatformAdmin || normalized.includes("tenant_admin");
21932
+ const isWorkspaceAdmin = isTenantAdmin || normalized.includes("workspace_admin") || normalized.includes("workspace_owner");
21933
+ return { isPlatformAdmin, isTenantAdmin, isWorkspaceAdmin };
21934
+ }
21935
+ function normalizeResolvedInteractivePrincipal(payload) {
21936
+ if ("ok" in payload && payload.ok === false) {
21937
+ throw new LucernControlPlaneIdentityError(payload);
21938
+ }
21939
+ const principalId = cleanString3(payload.principalId);
21940
+ const clerkId = cleanString3(payload.clerkId);
21941
+ const tenantId = cleanString3(payload.tenantId);
21942
+ if (!principalId || !clerkId || !tenantId) {
21943
+ throw new LucernControlPlaneIdentityError({
21944
+ ok: false,
21945
+ reason: "resolver_unavailable",
21946
+ message: "Control-plane principal resolver returned an incomplete principal context.",
21947
+ principalStatus: payload.principalStatus ?? "missing",
21948
+ tenantStatus: payload.tenantStatus,
21949
+ workspaceStatus: payload.workspaceStatus
21950
+ });
21951
+ }
21952
+ const roles = stringList(payload.roles);
21953
+ const scopes = stringList(payload.scopes);
21954
+ const workspaceId = cleanString3(payload.workspaceId) ?? null;
21955
+ const flags = adminFlags(roles);
21956
+ return {
21957
+ principalId,
21958
+ principalType: principalType(payload.principalType),
21959
+ clerkId,
21960
+ tenantId,
21961
+ workspaceId,
21962
+ roles,
21963
+ scopes,
21964
+ groupIds: stringList(payload.groupIds),
21965
+ permittedToolNames: stringList(payload.permittedToolNames),
21966
+ permittedPackKeys: stringList(payload.permittedPackKeys),
21967
+ principalStatus: cleanString3(payload.principalStatus) ?? "active",
21968
+ tenantStatus: cleanString3(payload.tenantStatus) ?? "active",
21969
+ workspaceStatus: cleanString3(payload.workspaceStatus) ?? (workspaceId ? "active" : "none"),
21970
+ isPlatformAdmin: typeof payload.isPlatformAdmin === "boolean" ? payload.isPlatformAdmin : flags.isPlatformAdmin,
21971
+ isTenantAdmin: typeof payload.isTenantAdmin === "boolean" ? payload.isTenantAdmin : flags.isTenantAdmin,
21972
+ isWorkspaceAdmin: typeof payload.isWorkspaceAdmin === "boolean" ? payload.isWorkspaceAdmin : flags.isWorkspaceAdmin,
21973
+ permit: {
21974
+ subject: cleanString3(payload.permit?.subject) ?? principalId,
21975
+ tenant: cleanString3(payload.permit?.tenant) ?? tenantId,
21976
+ ...workspaceId ? { workspace: cleanString3(payload.permit?.workspace) ?? workspaceId } : {}
21977
+ },
21978
+ authMode: "interactive_user",
21979
+ sessionId: payload.sessionId,
21980
+ delegatedBy: payload.delegatedBy,
21981
+ expiresAt: payload.expiresAt
21982
+ };
21983
+ }
21984
+ function createControlPlaneIdentityClient(config = {}) {
21985
+ const gateway = createGatewayRequestClient(config);
21986
+ return {
21987
+ async resolveInteractivePrincipal(input) {
21988
+ return gateway.request({
21989
+ path: "/api/platform/v1/control-plane/identity/resolve-interactive-principal",
21990
+ method: "POST",
21991
+ body: input
21992
+ }).then(
21993
+ (response) => mapGatewayData(response, normalizeResolvedInteractivePrincipal)
21994
+ );
21995
+ }
21996
+ };
21997
+ }
21998
+ function createControlPlaneClient(config = {}) {
21999
+ return {
22000
+ identity: createControlPlaneIdentityClient(config)
22001
+ };
22002
+ }
22003
+
21733
22004
  // ../sdk/src/identityClient.ts
21734
22005
  function createIdentityWhoamiClient(config = {}) {
21735
22006
  const gateway = createGatewayRequestClient(config);
@@ -21797,13 +22068,25 @@ function createIdentityClient(config = {}) {
21797
22068
  (response) => mapGatewayData(response, (data) => ({
21798
22069
  principalId: data.principalId,
21799
22070
  principalType: data.principalType,
22071
+ clerkId: data.clerkId,
21800
22072
  tenantId: data.tenantId ?? null,
21801
22073
  workspaceId: data.workspaceId ?? null,
21802
22074
  scopes: Array.isArray(data.scopes) ? data.scopes : [],
21803
22075
  roles: Array.isArray(data.roles) ? data.roles : [],
22076
+ groupIds: Array.isArray(data.groupIds) ? data.groupIds : [],
22077
+ permittedToolNames: Array.isArray(data.permittedToolNames) ? data.permittedToolNames : [],
22078
+ permittedPackKeys: Array.isArray(data.permittedPackKeys) ? data.permittedPackKeys : [],
22079
+ principalStatus: data.principalStatus,
22080
+ tenantStatus: data.tenantStatus,
22081
+ workspaceStatus: data.workspaceStatus,
21804
22082
  isPlatformAdmin: data.isPlatformAdmin === true,
21805
22083
  isTenantAdmin: data.isTenantAdmin === true,
21806
22084
  isWorkspaceAdmin: data.isWorkspaceAdmin === true,
22085
+ permit: data.permit ?? (data.tenantId ? {
22086
+ subject: data.principalId,
22087
+ tenant: data.tenantId,
22088
+ ...data.workspaceId ? { workspace: data.workspaceId } : {}
22089
+ } : void 0),
21807
22090
  authMode: data.authMode,
21808
22091
  sessionId: data.sessionId,
21809
22092
  delegatedBy: data.delegatedBy,
@@ -21811,6 +22094,19 @@ function createIdentityClient(config = {}) {
21811
22094
  }))
21812
22095
  );
21813
22096
  },
22097
+ /**
22098
+ * Resolve a Clerk subject through the tenant control-plane Permit projection.
22099
+ * @deprecated Prefer lucern.controlPlane.identity.resolveInteractivePrincipal().
22100
+ */
22101
+ async resolveInteractivePrincipal(input) {
22102
+ return gateway.request({
22103
+ path: "/api/platform/v1/control-plane/identity/resolve-interactive-principal",
22104
+ method: "POST",
22105
+ body: input
22106
+ }).then(
22107
+ (response) => mapGatewayData(response, normalizeResolvedInteractivePrincipal)
22108
+ );
22109
+ },
21814
22110
  /**
21815
22111
  * List principals in the current identity scope.
21816
22112
  */
@@ -22007,7 +22303,7 @@ var LucernAccessControlError = class extends LucernSdkAuthContextError {
22007
22303
  this.policyDecision = policyDecision;
22008
22304
  }
22009
22305
  };
22010
- function cleanString3(value) {
22306
+ function cleanString4(value) {
22011
22307
  const normalized = value?.trim();
22012
22308
  return normalized ? normalized : void 0;
22013
22309
  }
@@ -22022,7 +22318,7 @@ function cleanStringList2(values) {
22022
22318
  ];
22023
22319
  }
22024
22320
  function requireString2(value, reason, label) {
22025
- const normalized = cleanString3(value);
22321
+ const normalized = cleanString4(value);
22026
22322
  if (!normalized) {
22027
22323
  throw new LucernAccessControlError(
22028
22324
  reason,
@@ -22031,13 +22327,19 @@ function requireString2(value, reason, label) {
22031
22327
  }
22032
22328
  return normalized;
22033
22329
  }
22034
- function normalizePrincipalType(principalType) {
22035
- if (principalType === "agent") {
22330
+ function normalizePrincipalType(principalType2) {
22331
+ if (principalType2 === "agent") {
22036
22332
  return "agent";
22037
22333
  }
22038
- if (principalType === "service") {
22334
+ if (principalType2 === "service") {
22039
22335
  return "service";
22040
22336
  }
22337
+ if (principalType2 === "group") {
22338
+ return "group";
22339
+ }
22340
+ if (principalType2 === "external_viewer") {
22341
+ return "external_viewer";
22342
+ }
22041
22343
  return "human";
22042
22344
  }
22043
22345
  function aliasKey(alias) {
@@ -22046,15 +22348,15 @@ function aliasKey(alias) {
22046
22348
  function normalizeAliases(input, canonicalClerkUserId) {
22047
22349
  const aliases = /* @__PURE__ */ new Map();
22048
22350
  for (const alias of input ?? []) {
22049
- const externalSubjectId = cleanString3(alias.externalSubjectId);
22351
+ const externalSubjectId = cleanString4(alias.externalSubjectId);
22050
22352
  if (!externalSubjectId) {
22051
22353
  continue;
22052
22354
  }
22053
22355
  const normalized = {
22054
- provider: cleanString3(alias.provider) ?? "clerk",
22055
- providerProjectId: cleanString3(alias.providerProjectId),
22356
+ provider: cleanString4(alias.provider) ?? "clerk",
22357
+ providerProjectId: cleanString4(alias.providerProjectId),
22056
22358
  externalSubjectId,
22057
- status: cleanString3(alias.status)
22359
+ status: cleanString4(alias.status)
22058
22360
  };
22059
22361
  aliases.set(aliasKey(normalized), normalized);
22060
22362
  }
@@ -22099,10 +22401,10 @@ function normalizeCanonicalPrincipalIdentity(input, options = {}) {
22099
22401
  "principal_missing",
22100
22402
  "principalId"
22101
22403
  );
22102
- const principalType = normalizePrincipalType(principalInput.principalType);
22103
- const observedClerkId = cleanString3(options.observedClerkId);
22104
- const canonicalClerkUserId = cleanString3(principalInput.canonicalClerkUserId) ?? cleanString3(principalInput.clerkId);
22105
- if (principalType === "human" && !canonicalClerkUserId) {
22404
+ const principalType2 = normalizePrincipalType(principalInput.principalType);
22405
+ const observedClerkId = cleanString4(options.observedClerkId);
22406
+ const canonicalClerkUserId = cleanString4(principalInput.canonicalClerkUserId) ?? cleanString4(principalInput.clerkId);
22407
+ if (principalType2 === "human" && !canonicalClerkUserId) {
22106
22408
  throw new LucernAccessControlError(
22107
22409
  "clerk_alias_missing",
22108
22410
  "Human principals require one canonical Clerk user id."
@@ -22124,11 +22426,11 @@ function normalizeCanonicalPrincipalIdentity(input, options = {}) {
22124
22426
  }
22125
22427
  return {
22126
22428
  principalId,
22127
- principalType,
22429
+ principalType: principalType2,
22128
22430
  canonicalClerkUserId,
22129
22431
  clerkIdentityAliases: aliases,
22130
- tenantId: cleanString3(principalInput.tenantId),
22131
- workspaceId: cleanString3(principalInput.workspaceId),
22432
+ tenantId: cleanString4(principalInput.tenantId),
22433
+ workspaceId: cleanString4(principalInput.workspaceId),
22132
22434
  roles: cleanStringList2(principalInput.roles),
22133
22435
  scopes: cleanStringList2(principalInput.scopes)
22134
22436
  };
@@ -22153,7 +22455,7 @@ function buildPolicyInput(identity, input) {
22153
22455
  "tenant_missing",
22154
22456
  "tenantId"
22155
22457
  );
22156
- const workspaceId = cleanString3(input.workspaceId ?? identity.workspaceId);
22458
+ const workspaceId = cleanString4(input.workspaceId ?? identity.workspaceId);
22157
22459
  if (resourceRequiresWorkspace(input.resource) && !workspaceId) {
22158
22460
  throw new LucernAccessControlError(
22159
22461
  "workspace_missing",
@@ -23553,12 +23855,12 @@ function createGraphClient(config = {}) {
23553
23855
  }
23554
23856
 
23555
23857
  // ../sdk/src/topicsClient.ts
23556
- function cleanString4(value) {
23858
+ function cleanString5(value) {
23557
23859
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
23558
23860
  }
23559
23861
  function normalizeTopicRecord(value) {
23560
23862
  const record = asRecord(value);
23561
- const topicId = cleanString4(record.topicId) ?? cleanString4(record.id) ?? cleanString4(record._id);
23863
+ const topicId = cleanString5(record.topicId) ?? cleanString5(record.id) ?? cleanString5(record._id);
23562
23864
  return withTopicAlias({
23563
23865
  ...record,
23564
23866
  ...topicId ? { topicId } : {}
@@ -24771,7 +25073,7 @@ function createEmbeddingsClient(config = {}) {
24771
25073
  }
24772
25074
 
24773
25075
  // ../sdk/src/contextClient.ts
24774
- function cleanString5(value) {
25076
+ function cleanString6(value) {
24775
25077
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
24776
25078
  }
24777
25079
  function cleanNumber(value) {
@@ -24783,11 +25085,11 @@ function cleanBoolean(value) {
24783
25085
  function buildCompileContextRequest(topicIdOrInput = {}, input = {}) {
24784
25086
  const effectiveInput = typeof topicIdOrInput === "string" ? input : topicIdOrInput;
24785
25087
  const payload = {};
24786
- const topicId = typeof topicIdOrInput === "string" ? cleanString5(topicIdOrInput) : cleanString5(effectiveInput.topicId);
25088
+ const topicId = typeof topicIdOrInput === "string" ? cleanString6(topicIdOrInput) : cleanString6(effectiveInput.topicId);
24787
25089
  if (topicId) {
24788
25090
  payload.topicId = topicId;
24789
25091
  }
24790
- const query5 = cleanString5(effectiveInput.query);
25092
+ const query5 = cleanString6(effectiveInput.query);
24791
25093
  if (query5) {
24792
25094
  payload.query = query5;
24793
25095
  }
@@ -24795,7 +25097,7 @@ function buildCompileContextRequest(topicIdOrInput = {}, input = {}) {
24795
25097
  if (budget !== void 0) {
24796
25098
  payload.budget = budget;
24797
25099
  }
24798
- const ranking = cleanString5(effectiveInput.ranking) ?? cleanString5(effectiveInput.rankingProfile);
25100
+ const ranking = cleanString6(effectiveInput.ranking) ?? cleanString6(effectiveInput.rankingProfile);
24799
25101
  if (ranking) {
24800
25102
  payload.ranking = ranking;
24801
25103
  }
@@ -24811,7 +25113,7 @@ function buildCompileContextRequest(topicIdOrInput = {}, input = {}) {
24811
25113
  if (includeEntities !== void 0) {
24812
25114
  payload.includeEntities = includeEntities;
24813
25115
  }
24814
- const mode = cleanString5(effectiveInput.mode);
25116
+ const mode = cleanString6(effectiveInput.mode);
24815
25117
  if (mode) {
24816
25118
  payload.mode = mode;
24817
25119
  }
@@ -24819,11 +25121,11 @@ function buildCompileContextRequest(topicIdOrInput = {}, input = {}) {
24819
25121
  if (includeFailures !== void 0) {
24820
25122
  payload.includeFailures = includeFailures;
24821
25123
  }
24822
- const worktreeId = cleanString5(effectiveInput.worktreeId);
25124
+ const worktreeId = cleanString6(effectiveInput.worktreeId);
24823
25125
  if (worktreeId) {
24824
25126
  payload.worktreeId = worktreeId;
24825
25127
  }
24826
- const sessionId = cleanString5(effectiveInput.sessionId);
25128
+ const sessionId = cleanString6(effectiveInput.sessionId);
24827
25129
  if (sessionId) {
24828
25130
  payload.sessionId = sessionId;
24829
25131
  }
@@ -25832,6 +26134,7 @@ var FUNCTION_SURFACE_METHOD_PATHS = [
25832
26134
  "contracts.evaluateContract",
25833
26135
  "contracts.getContractStatus",
25834
26136
  "contradictions.flagContradiction",
26137
+ "controlPlane.identity.resolveInteractivePrincipal",
25835
26138
  "coordination.broadcastMessage",
25836
26139
  "coordination.claimFiles",
25837
26140
  "coordination.endSession",
@@ -26037,6 +26340,7 @@ var CONTRACTS = {
26037
26340
  "remove_edges_between": { method: "DELETE", path: "/edges/between", kind: "mutation", idempotent: true, surfaceIntent: "mcp_analysis" },
26038
26341
  "remove_lens_from_topic": { method: "DELETE", path: "/lenses/apply", kind: "mutation", idempotent: true, surfaceIntent: "mcp_workflow" },
26039
26342
  "resolve_effective_ontology": { method: "POST", path: "/ontologies/effective", kind: "query", idempotent: false, surfaceIntent: "mcp_workflow" },
26343
+ "resolve_interactive_principal": { method: "POST", path: "/control-plane/identity/resolve-interactive-principal", kind: "query", idempotent: false, surfaceIntent: "mcp_core" },
26040
26344
  "run_graph_intelligence_query": { method: "POST", path: "/graph-intelligence/run", kind: "query", idempotent: false, surfaceIntent: "mcp_analysis" },
26041
26345
  "search_beliefs": { method: "POST", path: "/beliefs/search", kind: "query", idempotent: false, surfaceIntent: "mcp_core" },
26042
26346
  "search_evidence": { method: "POST", path: "/evidence/search", kind: "query", idempotent: false, surfaceIntent: "mcp_core" },
@@ -26419,6 +26723,9 @@ function createFunctionSurfaceClient(config = {}) {
26419
26723
  resolveEffectiveOntology(input = {}, idempotencyKey) {
26420
26724
  return execute("resolve_effective_ontology", input, idempotencyKey);
26421
26725
  },
26726
+ resolveInteractivePrincipal(input = {}, idempotencyKey) {
26727
+ return execute("resolve_interactive_principal", input, idempotencyKey);
26728
+ },
26422
26729
  runGraphIntelligenceQuery(input = {}, idempotencyKey) {
26423
26730
  return execute("run_graph_intelligence_query", input, idempotencyKey);
26424
26731
  },
@@ -26679,7 +26986,7 @@ var ORG_GRAPH_SEARCH_FIELDS = [
26679
26986
  "cursor",
26680
26987
  "provenanceScope"
26681
26988
  ];
26682
- function cleanString6(value, label) {
26989
+ function cleanString7(value, label) {
26683
26990
  const normalized = value?.trim();
26684
26991
  if (!normalized) {
26685
26992
  throw new Error(`${label} is required`);
@@ -26701,9 +27008,9 @@ function searchBody(input) {
26701
27008
  "orgGraphSearch.search"
26702
27009
  );
26703
27010
  return {
26704
- tenantId: cleanString6(input.tenantId, "tenantId"),
26705
- workspaceId: cleanString6(input.workspaceId, "workspaceId"),
26706
- query: cleanString6(input.query, "query"),
27011
+ tenantId: cleanString7(input.tenantId, "tenantId"),
27012
+ workspaceId: cleanString7(input.workspaceId, "workspaceId"),
27013
+ query: cleanString7(input.query, "query"),
26707
27014
  nodeTypes: input.nodeTypes,
26708
27015
  minConfidence: input.minConfidence,
26709
27016
  limit: input.limit,
@@ -26713,8 +27020,8 @@ function searchBody(input) {
26713
27020
  }
26714
27021
  function listQuery2(input) {
26715
27022
  return {
26716
- tenantId: cleanString6(input.tenantId, "tenantId"),
26717
- workspaceId: cleanString6(input.workspaceId, "workspaceId"),
27023
+ tenantId: cleanString7(input.tenantId, "tenantId"),
27024
+ workspaceId: cleanString7(input.workspaceId, "workspaceId"),
26718
27025
  nodeTypes: input.nodeTypes?.join(","),
26719
27026
  minConfidence: input.minConfidence,
26720
27027
  limit: input.limit,
@@ -26748,8 +27055,8 @@ function createOrgGraphSearchClient(config = {}) {
26748
27055
  return gateway.request({
26749
27056
  path: `/api/platform/v1/org-graph-search/nodes/${nodePath}${toQueryString(
26750
27057
  {
26751
- tenantId: cleanString6(input.tenantId, "tenantId"),
26752
- workspaceId: cleanString6(input.workspaceId, "workspaceId"),
27058
+ tenantId: cleanString7(input.tenantId, "tenantId"),
27059
+ workspaceId: cleanString7(input.workspaceId, "workspaceId"),
26753
27060
  globalId: nodeId ? void 0 : globalId
26754
27061
  }
26755
27062
  )}`
@@ -27714,7 +28021,7 @@ function createToolRegistryClient(config = {}) {
27714
28021
  }
27715
28022
 
27716
28023
  // ../sdk/src/version.ts
27717
- var LUCERN_SDK_VERSION = "0.3.0-alpha.12";
28024
+ var LUCERN_SDK_VERSION = "0.3.0-alpha.14";
27718
28025
 
27719
28026
  // ../sdk/src/workflowClient.ts
27720
28027
  function normalizeLensQuery(value) {
@@ -28191,6 +28498,7 @@ function createLucernClient(config = {}) {
28191
28498
  const ontologyLinksClient = createOntologyLinksClient(gatewayConfig);
28192
28499
  const orgGraphSearchClient = createOrgGraphSearchClient(gatewayConfig);
28193
28500
  const functionSurfaceClient = createFunctionSurfaceClient(gatewayConfig);
28501
+ const controlPlaneClient = createControlPlaneClient(gatewayConfig);
28194
28502
  const toolRegistryClient = createToolRegistryClient(gatewayConfig);
28195
28503
  const modelRuntimeClient = createModelRuntimeClient(gatewayConfig);
28196
28504
  const packsClient = createPacksClient(gatewayConfig);
@@ -29854,9 +30162,16 @@ function createLucernClient(config = {}) {
29854
30162
  disable: packsClient.disable
29855
30163
  },
29856
30164
  nodes: nodesNamespace,
30165
+ controlPlane: {
30166
+ identity: {
30167
+ resolveInteractivePrincipal: controlPlaneClient.identity.resolveInteractivePrincipal
30168
+ },
30169
+ raw: controlPlaneClient
30170
+ },
29857
30171
  identity: {
29858
30172
  ...identityFacade,
29859
30173
  access: accessControlClient,
30174
+ resolveInteractivePrincipal: identityClient.resolveInteractivePrincipal,
29860
30175
  evaluatePolicy: identityClient.evaluatePolicy,
29861
30176
  recordPolicyDecision: identityClient.recordPolicyDecision,
29862
30177
  putSecretReference: identityClient.putSecretReference,
@@ -29901,6 +30216,7 @@ function createLucernClient(config = {}) {
29901
30216
  ontologyLinks: ontologyLinksClient,
29902
30217
  orgGraphSearch: orgGraphSearchClient,
29903
30218
  functionSurface: functionSurfaceClient,
30219
+ controlPlane: controlPlaneClient,
29904
30220
  toolRegistry: toolRegistryClient,
29905
30221
  modelRuntime: modelRuntimeClient,
29906
30222
  packs: packsClient,
@@ -29918,7 +30234,7 @@ function createLucernClient(config = {}) {
29918
30234
  }
29919
30235
 
29920
30236
  // ../sdk/src/facade/context.ts
29921
- function cleanString7(value) {
30237
+ function cleanString8(value) {
29922
30238
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
29923
30239
  }
29924
30240
  function cleanNumber2(value) {
@@ -29930,11 +30246,11 @@ function cleanBoolean2(value) {
29930
30246
  function buildCompileContextRequest2(topicIdOrInput = {}, input = {}) {
29931
30247
  const effectiveInput = typeof topicIdOrInput === "string" ? input : topicIdOrInput;
29932
30248
  const payload = {};
29933
- const topicId = typeof topicIdOrInput === "string" ? cleanString7(topicIdOrInput) : cleanString7(effectiveInput.topicId);
30249
+ const topicId = typeof topicIdOrInput === "string" ? cleanString8(topicIdOrInput) : cleanString8(effectiveInput.topicId);
29934
30250
  if (topicId) {
29935
30251
  payload.topicId = topicId;
29936
30252
  }
29937
- const query5 = cleanString7(effectiveInput.query);
30253
+ const query5 = cleanString8(effectiveInput.query);
29938
30254
  if (query5) {
29939
30255
  payload.query = query5;
29940
30256
  }
@@ -29942,7 +30258,7 @@ function buildCompileContextRequest2(topicIdOrInput = {}, input = {}) {
29942
30258
  if (budget !== void 0) {
29943
30259
  payload.budget = budget;
29944
30260
  }
29945
- const ranking = cleanString7(effectiveInput.ranking) ?? cleanString7(effectiveInput.rankingProfile);
30261
+ const ranking = cleanString8(effectiveInput.ranking) ?? cleanString8(effectiveInput.rankingProfile);
29946
30262
  if (ranking) {
29947
30263
  payload.ranking = ranking;
29948
30264
  }
@@ -29958,7 +30274,7 @@ function buildCompileContextRequest2(topicIdOrInput = {}, input = {}) {
29958
30274
  if (includeEntities !== void 0) {
29959
30275
  payload.includeEntities = includeEntities;
29960
30276
  }
29961
- const mode = cleanString7(effectiveInput.mode);
30277
+ const mode = cleanString8(effectiveInput.mode);
29962
30278
  if (mode) {
29963
30279
  payload.mode = mode;
29964
30280
  }
@@ -29966,11 +30282,11 @@ function buildCompileContextRequest2(topicIdOrInput = {}, input = {}) {
29966
30282
  if (includeFailures !== void 0) {
29967
30283
  payload.includeFailures = includeFailures;
29968
30284
  }
29969
- const worktreeId = cleanString7(effectiveInput.worktreeId);
30285
+ const worktreeId = cleanString8(effectiveInput.worktreeId);
29970
30286
  if (worktreeId) {
29971
30287
  payload.worktreeId = worktreeId;
29972
30288
  }
29973
- const sessionId = cleanString7(effectiveInput.sessionId);
30289
+ const sessionId = cleanString8(effectiveInput.sessionId);
29974
30290
  if (sessionId) {
29975
30291
  payload.sessionId = sessionId;
29976
30292
  }
@@ -31392,7 +31708,13 @@ var SESSION_AUTH_MODES = [
31392
31708
  "tenant_api_key",
31393
31709
  "session_token"
31394
31710
  ];
31395
- var SESSION_PRINCIPAL_TYPES = ["human", "service", "agent"];
31711
+ var SESSION_PRINCIPAL_TYPES = [
31712
+ "human",
31713
+ "service",
31714
+ "agent",
31715
+ "group",
31716
+ "external_viewer"
31717
+ ];
31396
31718
  var SESSION_LIFECYCLE_STATUSES = [
31397
31719
  "active",
31398
31720
  "expired",
@@ -31405,6 +31727,12 @@ function inferSessionPrincipalType(principalId) {
31405
31727
  if (principalId.startsWith("agent:")) {
31406
31728
  return "agent";
31407
31729
  }
31730
+ if (principalId.startsWith("group:")) {
31731
+ return "group";
31732
+ }
31733
+ if (principalId.startsWith("external:") || principalId.startsWith("external_viewer:")) {
31734
+ return "external_viewer";
31735
+ }
31408
31736
  return "service";
31409
31737
  }
31410
31738
  function normalizeDelegationChain(args) {
@@ -34620,7 +34948,7 @@ function createLucernStandaloneMcpServer(options) {
34620
34948
  });
34621
34949
  const server = new McpServer({
34622
34950
  name: "lucern-mcp",
34623
- version: "0.3.0-alpha.12"
34951
+ version: "0.3.0-alpha.14"
34624
34952
  });
34625
34953
  registerTools(server, runtime);
34626
34954
  const resources = registerResources(server, runtime, observationStore);