@lucern/mcp 0.3.0-alpha.11 → 0.3.0-alpha.13

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",
@@ -4719,7 +4748,9 @@ var permitObjectType = z.enum([
4719
4748
  "group",
4720
4749
  "resource_instance",
4721
4750
  "relationship_tuple",
4722
- "role_assignment"
4751
+ "role_assignment",
4752
+ "attribute_binding",
4753
+ "policy_bundle"
4723
4754
  ]);
4724
4755
  var permitOutboxOperation = z.enum([
4725
4756
  "upsert",
@@ -4825,7 +4856,10 @@ defineTable({
4825
4856
  }),
4826
4857
  indices: [
4827
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"] },
4828
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"] },
4829
4863
  {
4830
4864
  kind: "index",
4831
4865
  name: "by_tenant_provider_alias",
@@ -8193,6 +8227,40 @@ var GENERATED_INFISICAL_RUNTIME_ENV = {
8193
8227
  ],
8194
8228
  "description": "Canonical Lucern API gateway URL. Canonical Lucern API gateway base URL. Older names remain aliases only."
8195
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
+ },
8196
8264
  {
8197
8265
  "canonicalName": "LUCERN_CLI_SESSION_TTL_MS",
8198
8266
  "envNames": [
@@ -8516,6 +8584,54 @@ var GENERATED_INFISICAL_RUNTIME_ENV = {
8516
8584
  ],
8517
8585
  "description": "Optional Permit PDP URL override."
8518
8586
  },
8587
+ {
8588
+ "secretId": "platform.permit.webhook-secret",
8589
+ "canonicalName": "LUCERN_PERMIT_WEBHOOK_SECRET",
8590
+ "envNames": [
8591
+ "LUCERN_PERMIT_WEBHOOK_SECRET",
8592
+ "PERMIT_WEBHOOK_SECRET"
8593
+ ],
8594
+ "aliases": [
8595
+ "PERMIT_WEBHOOK_SECRET"
8596
+ ],
8597
+ "writeNames": [
8598
+ "LUCERN_PERMIT_WEBHOOK_SECRET"
8599
+ ],
8600
+ "required": true,
8601
+ "secret": true,
8602
+ "public": false,
8603
+ "sourcePath": "/platform/permit",
8604
+ "environmentPolicy": "environment_specific",
8605
+ "consumers": [
8606
+ "mc-convex",
8607
+ "lucern-gateway",
8608
+ "mc-operator-tooling"
8609
+ ],
8610
+ "destinations": [
8611
+ {
8612
+ "kind": "convex",
8613
+ "target": "master-control",
8614
+ "writeNames": [
8615
+ "LUCERN_PERMIT_WEBHOOK_SECRET"
8616
+ ]
8617
+ },
8618
+ {
8619
+ "kind": "vercel",
8620
+ "target": "lucern-gateway",
8621
+ "writeNames": [
8622
+ "LUCERN_PERMIT_WEBHOOK_SECRET"
8623
+ ]
8624
+ },
8625
+ {
8626
+ "kind": "operator_local",
8627
+ "target": "mc-credential-maintenance",
8628
+ "writeNames": [
8629
+ "LUCERN_PERMIT_WEBHOOK_SECRET"
8630
+ ]
8631
+ }
8632
+ ],
8633
+ "description": "Permit.io webhook secret used by gateway and MC webhook handlers. Must fail closed if missing."
8634
+ },
8519
8635
  {
8520
8636
  "secretId": "platform.runtime.require-deployment-host-registry",
8521
8637
  "canonicalName": "LUCERN_REQUIRE_DEPLOYMENT_HOST_REGISTRY",
@@ -12604,7 +12720,7 @@ var IDENTITY_WHOAMI = {
12604
12720
  description: "Canonical identity summary for the current session",
12605
12721
  fields: {
12606
12722
  principalId: "string \u2014 canonical federated principal identifier",
12607
- principalType: "string \u2014 human, service, or agent",
12723
+ principalType: "string \u2014 human, service, agent, group, or external_viewer",
12608
12724
  tenantId: "string | undefined \u2014 resolved tenant scope",
12609
12725
  workspaceId: "string | undefined \u2014 resolved workspace scope",
12610
12726
  scopes: "string[] | undefined \u2014 granted scopes for this session",
@@ -12615,6 +12731,49 @@ var IDENTITY_WHOAMI = {
12615
12731
  ontologyPrimitive: "identity",
12616
12732
  tier: "workhorse"
12617
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
+ };
12618
12777
  var COMPILE_CONTEXT = {
12619
12778
  name: "compile_context",
12620
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.",
@@ -14517,6 +14676,7 @@ var MCP_TOOL_CONTRACTS = {
14517
14676
  update_worktree_targets: UPDATE_WORKTREE_TARGETS,
14518
14677
  update_worktree_metadata: UPDATE_WORKTREE_METADATA,
14519
14678
  identity_whoami: IDENTITY_WHOAMI,
14679
+ resolve_interactive_principal: RESOLVE_INTERACTIVE_PRINCIPAL,
14520
14680
  compile_context: COMPILE_CONTEXT,
14521
14681
  record_scope_learning: RECORD_SCOPE_LEARNING,
14522
14682
  pipeline_snapshot: PIPELINE_SNAPSHOT,
@@ -14646,6 +14806,7 @@ function entries(names, surfaceClass, surfaceIntent, surfaces, rationale) {
14646
14806
  var MCP_CORE_OPERATION_NAMES = [
14647
14807
  "compile_context",
14648
14808
  "identity_whoami",
14809
+ "resolve_interactive_principal",
14649
14810
  "check_permission",
14650
14811
  "filter_by_permission",
14651
14812
  "create_belief",
@@ -15199,7 +15360,13 @@ function surfaceContract(args) {
15199
15360
  scopes: args.scopes ?? [
15200
15361
  args.kind === "query" ? `${args.domain}.read` : `${args.domain}.write`
15201
15362
  ],
15202
- allowedPrincipalTypes: ["user", "service", "agent"]
15363
+ allowedPrincipalTypes: [
15364
+ "user",
15365
+ "service",
15366
+ "agent",
15367
+ "group",
15368
+ "external_viewer"
15369
+ ]
15203
15370
  },
15204
15371
  convex: args.convex,
15205
15372
  gateway: args.gateway,
@@ -15341,8 +15508,6 @@ var contextContracts = [
15341
15508
  args: observationContextArgs
15342
15509
  })
15343
15510
  ];
15344
-
15345
- // ../contracts/src/function-registry/identity.ts
15346
15511
  var withPrincipal = (input, context) => ({
15347
15512
  ...input,
15348
15513
  tenantId: input.tenantId ?? context.tenantId,
@@ -15368,6 +15533,28 @@ var identityContracts = [
15368
15533
  inputProjection: withPrincipal
15369
15534
  }
15370
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
+ }),
15371
15558
  surfaceContract({
15372
15559
  name: "check_permission",
15373
15560
  kind: "query",
@@ -19172,6 +19359,13 @@ var TENANT_BOOTSTRAP_TABLE_REQUIREMENTS = [
19172
19359
  copyMode: "none",
19173
19360
  description: "Deliberation sessions are created by tenant workflows."
19174
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
+ },
19175
19369
  {
19176
19370
  component: "kernel",
19177
19371
  table: "epistemicAudit",
@@ -20351,6 +20545,7 @@ __export(src_exports, {
20351
20545
  LUCERN_SDK_VERSION: () => LUCERN_SDK_VERSION,
20352
20546
  LucernAccessControlError: () => LucernAccessControlError,
20353
20547
  LucernApiError: () => LucernApiError,
20548
+ LucernControlPlaneIdentityError: () => LucernControlPlaneIdentityError,
20354
20549
  LucernSdkAuthContextError: () => LucernSdkAuthContextError,
20355
20550
  MANAGE_WRITE_POLICY: () => MANAGE_WRITE_POLICY,
20356
20551
  MATCH_ENTITY_TYPE: () => MATCH_ENTITY_TYPE,
@@ -20382,6 +20577,7 @@ __export(src_exports, {
20382
20577
  REMOVE_EDGES_BETWEEN: () => REMOVE_EDGES_BETWEEN,
20383
20578
  REMOVE_LENS_FROM_TOPIC: () => REMOVE_LENS_FROM_TOPIC,
20384
20579
  RESOLVE_EFFECTIVE_ONTOLOGY: () => RESOLVE_EFFECTIVE_ONTOLOGY,
20580
+ RESOLVE_INTERACTIVE_PRINCIPAL: () => RESOLVE_INTERACTIVE_PRINCIPAL,
20385
20581
  RUN_GRAPH_INTELLIGENCE_QUERY: () => RUN_GRAPH_INTELLIGENCE_QUERY,
20386
20582
  SEARCH_BELIEFS: () => SEARCH_BELIEFS,
20387
20583
  SEARCH_EVIDENCE: () => SEARCH_EVIDENCE,
@@ -20447,6 +20643,8 @@ __export(src_exports, {
20447
20643
  createCanonicalAuthHeaders: () => createCanonicalAuthHeaders,
20448
20644
  createContextClient: () => createContextClient,
20449
20645
  createContextFacade: () => createContextFacade,
20646
+ createControlPlaneClient: () => createControlPlaneClient,
20647
+ createControlPlaneIdentityClient: () => createControlPlaneIdentityClient,
20450
20648
  createDecisionsClient: () => createDecisionsClient,
20451
20649
  createEmbeddingsClient: () => createEmbeddingsClient,
20452
20650
  createEventId: () => createEventId,
@@ -20520,6 +20718,7 @@ __export(src_exports, {
20520
20718
  normalizeDelegationChain: () => normalizeDelegationChain,
20521
20719
  normalizeNodeVerificationStatus: () => normalizeNodeVerificationStatus,
20522
20720
  normalizeNodeWriteInput: () => normalizeNodeWriteInput,
20721
+ normalizeResolvedInteractivePrincipal: () => normalizeResolvedInteractivePrincipal,
20523
20722
  normalizeRetentionDays: () => normalizeRetentionDays,
20524
20723
  normalizeTopicQuery: () => normalizeTopicQuery,
20525
20724
  normalizeWebhookPatterns: () => normalizeWebhookPatterns,
@@ -20609,14 +20808,14 @@ function requireString(value, reason, label) {
20609
20808
  }
20610
20809
  return normalized;
20611
20810
  }
20612
- function requirePrincipalType(principalType) {
20613
- if (!principalType) {
20811
+ function requirePrincipalType(principalType2) {
20812
+ if (!principalType2) {
20614
20813
  throw new LucernSdkAuthContextError(
20615
20814
  "principal_missing",
20616
20815
  "Canonical Lucern SDK auth context is missing principalType."
20617
20816
  );
20618
20817
  }
20619
- return principalType;
20818
+ return principalType2;
20620
20819
  }
20621
20820
  function requireAuthMode(authMode) {
20622
20821
  if (!authMode) {
@@ -20662,7 +20861,7 @@ function normalizeCanonicalLucernAuthContext(input) {
20662
20861
  );
20663
20862
  const roles = cleanStringList(input.roles);
20664
20863
  const scopes = cleanStringList(input.scopes);
20665
- const principalType = requirePrincipalType(input.principalType);
20864
+ const principalType2 = requirePrincipalType(input.principalType);
20666
20865
  const authMode = requireAuthMode(input.authMode);
20667
20866
  const roleBasedInteractiveAuth = authMode === "interactive_user" && roles.length > 0;
20668
20867
  if (roles.length === 0 || scopes.length === 0 && !roleBasedInteractiveAuth) {
@@ -20691,7 +20890,7 @@ function normalizeCanonicalLucernAuthContext(input) {
20691
20890
  principalId,
20692
20891
  tenantId,
20693
20892
  workspaceId,
20694
- principalType,
20893
+ principalType: principalType2,
20695
20894
  authMode,
20696
20895
  roles,
20697
20896
  scopes,
@@ -21680,6 +21879,128 @@ function listResultFromEnvelope(data, legacyKey) {
21680
21879
  );
21681
21880
  }
21682
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
+
21683
22004
  // ../sdk/src/identityClient.ts
21684
22005
  function createIdentityWhoamiClient(config = {}) {
21685
22006
  const gateway = createGatewayRequestClient(config);
@@ -21747,13 +22068,25 @@ function createIdentityClient(config = {}) {
21747
22068
  (response) => mapGatewayData(response, (data) => ({
21748
22069
  principalId: data.principalId,
21749
22070
  principalType: data.principalType,
22071
+ clerkId: data.clerkId,
21750
22072
  tenantId: data.tenantId ?? null,
21751
22073
  workspaceId: data.workspaceId ?? null,
21752
22074
  scopes: Array.isArray(data.scopes) ? data.scopes : [],
21753
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,
21754
22082
  isPlatformAdmin: data.isPlatformAdmin === true,
21755
22083
  isTenantAdmin: data.isTenantAdmin === true,
21756
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),
21757
22090
  authMode: data.authMode,
21758
22091
  sessionId: data.sessionId,
21759
22092
  delegatedBy: data.delegatedBy,
@@ -21761,6 +22094,19 @@ function createIdentityClient(config = {}) {
21761
22094
  }))
21762
22095
  );
21763
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
+ },
21764
22110
  /**
21765
22111
  * List principals in the current identity scope.
21766
22112
  */
@@ -21957,7 +22303,7 @@ var LucernAccessControlError = class extends LucernSdkAuthContextError {
21957
22303
  this.policyDecision = policyDecision;
21958
22304
  }
21959
22305
  };
21960
- function cleanString3(value) {
22306
+ function cleanString4(value) {
21961
22307
  const normalized = value?.trim();
21962
22308
  return normalized ? normalized : void 0;
21963
22309
  }
@@ -21972,7 +22318,7 @@ function cleanStringList2(values) {
21972
22318
  ];
21973
22319
  }
21974
22320
  function requireString2(value, reason, label) {
21975
- const normalized = cleanString3(value);
22321
+ const normalized = cleanString4(value);
21976
22322
  if (!normalized) {
21977
22323
  throw new LucernAccessControlError(
21978
22324
  reason,
@@ -21981,13 +22327,19 @@ function requireString2(value, reason, label) {
21981
22327
  }
21982
22328
  return normalized;
21983
22329
  }
21984
- function normalizePrincipalType(principalType) {
21985
- if (principalType === "agent") {
22330
+ function normalizePrincipalType(principalType2) {
22331
+ if (principalType2 === "agent") {
21986
22332
  return "agent";
21987
22333
  }
21988
- if (principalType === "service") {
22334
+ if (principalType2 === "service") {
21989
22335
  return "service";
21990
22336
  }
22337
+ if (principalType2 === "group") {
22338
+ return "group";
22339
+ }
22340
+ if (principalType2 === "external_viewer") {
22341
+ return "external_viewer";
22342
+ }
21991
22343
  return "human";
21992
22344
  }
21993
22345
  function aliasKey(alias) {
@@ -21996,15 +22348,15 @@ function aliasKey(alias) {
21996
22348
  function normalizeAliases(input, canonicalClerkUserId) {
21997
22349
  const aliases = /* @__PURE__ */ new Map();
21998
22350
  for (const alias of input ?? []) {
21999
- const externalSubjectId = cleanString3(alias.externalSubjectId);
22351
+ const externalSubjectId = cleanString4(alias.externalSubjectId);
22000
22352
  if (!externalSubjectId) {
22001
22353
  continue;
22002
22354
  }
22003
22355
  const normalized = {
22004
- provider: cleanString3(alias.provider) ?? "clerk",
22005
- providerProjectId: cleanString3(alias.providerProjectId),
22356
+ provider: cleanString4(alias.provider) ?? "clerk",
22357
+ providerProjectId: cleanString4(alias.providerProjectId),
22006
22358
  externalSubjectId,
22007
- status: cleanString3(alias.status)
22359
+ status: cleanString4(alias.status)
22008
22360
  };
22009
22361
  aliases.set(aliasKey(normalized), normalized);
22010
22362
  }
@@ -22049,10 +22401,10 @@ function normalizeCanonicalPrincipalIdentity(input, options = {}) {
22049
22401
  "principal_missing",
22050
22402
  "principalId"
22051
22403
  );
22052
- const principalType = normalizePrincipalType(principalInput.principalType);
22053
- const observedClerkId = cleanString3(options.observedClerkId);
22054
- const canonicalClerkUserId = cleanString3(principalInput.canonicalClerkUserId) ?? cleanString3(principalInput.clerkId);
22055
- 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) {
22056
22408
  throw new LucernAccessControlError(
22057
22409
  "clerk_alias_missing",
22058
22410
  "Human principals require one canonical Clerk user id."
@@ -22074,11 +22426,11 @@ function normalizeCanonicalPrincipalIdentity(input, options = {}) {
22074
22426
  }
22075
22427
  return {
22076
22428
  principalId,
22077
- principalType,
22429
+ principalType: principalType2,
22078
22430
  canonicalClerkUserId,
22079
22431
  clerkIdentityAliases: aliases,
22080
- tenantId: cleanString3(principalInput.tenantId),
22081
- workspaceId: cleanString3(principalInput.workspaceId),
22432
+ tenantId: cleanString4(principalInput.tenantId),
22433
+ workspaceId: cleanString4(principalInput.workspaceId),
22082
22434
  roles: cleanStringList2(principalInput.roles),
22083
22435
  scopes: cleanStringList2(principalInput.scopes)
22084
22436
  };
@@ -22103,7 +22455,7 @@ function buildPolicyInput(identity, input) {
22103
22455
  "tenant_missing",
22104
22456
  "tenantId"
22105
22457
  );
22106
- const workspaceId = cleanString3(input.workspaceId ?? identity.workspaceId);
22458
+ const workspaceId = cleanString4(input.workspaceId ?? identity.workspaceId);
22107
22459
  if (resourceRequiresWorkspace(input.resource) && !workspaceId) {
22108
22460
  throw new LucernAccessControlError(
22109
22461
  "workspace_missing",
@@ -23503,12 +23855,12 @@ function createGraphClient(config = {}) {
23503
23855
  }
23504
23856
 
23505
23857
  // ../sdk/src/topicsClient.ts
23506
- function cleanString4(value) {
23858
+ function cleanString5(value) {
23507
23859
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
23508
23860
  }
23509
23861
  function normalizeTopicRecord(value) {
23510
23862
  const record = asRecord(value);
23511
- const topicId = cleanString4(record.topicId) ?? cleanString4(record.id) ?? cleanString4(record._id);
23863
+ const topicId = cleanString5(record.topicId) ?? cleanString5(record.id) ?? cleanString5(record._id);
23512
23864
  return withTopicAlias({
23513
23865
  ...record,
23514
23866
  ...topicId ? { topicId } : {}
@@ -24721,7 +25073,7 @@ function createEmbeddingsClient(config = {}) {
24721
25073
  }
24722
25074
 
24723
25075
  // ../sdk/src/contextClient.ts
24724
- function cleanString5(value) {
25076
+ function cleanString6(value) {
24725
25077
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
24726
25078
  }
24727
25079
  function cleanNumber(value) {
@@ -24733,11 +25085,11 @@ function cleanBoolean(value) {
24733
25085
  function buildCompileContextRequest(topicIdOrInput = {}, input = {}) {
24734
25086
  const effectiveInput = typeof topicIdOrInput === "string" ? input : topicIdOrInput;
24735
25087
  const payload = {};
24736
- const topicId = typeof topicIdOrInput === "string" ? cleanString5(topicIdOrInput) : cleanString5(effectiveInput.topicId);
25088
+ const topicId = typeof topicIdOrInput === "string" ? cleanString6(topicIdOrInput) : cleanString6(effectiveInput.topicId);
24737
25089
  if (topicId) {
24738
25090
  payload.topicId = topicId;
24739
25091
  }
24740
- const query5 = cleanString5(effectiveInput.query);
25092
+ const query5 = cleanString6(effectiveInput.query);
24741
25093
  if (query5) {
24742
25094
  payload.query = query5;
24743
25095
  }
@@ -24745,7 +25097,7 @@ function buildCompileContextRequest(topicIdOrInput = {}, input = {}) {
24745
25097
  if (budget !== void 0) {
24746
25098
  payload.budget = budget;
24747
25099
  }
24748
- const ranking = cleanString5(effectiveInput.ranking) ?? cleanString5(effectiveInput.rankingProfile);
25100
+ const ranking = cleanString6(effectiveInput.ranking) ?? cleanString6(effectiveInput.rankingProfile);
24749
25101
  if (ranking) {
24750
25102
  payload.ranking = ranking;
24751
25103
  }
@@ -24761,7 +25113,7 @@ function buildCompileContextRequest(topicIdOrInput = {}, input = {}) {
24761
25113
  if (includeEntities !== void 0) {
24762
25114
  payload.includeEntities = includeEntities;
24763
25115
  }
24764
- const mode = cleanString5(effectiveInput.mode);
25116
+ const mode = cleanString6(effectiveInput.mode);
24765
25117
  if (mode) {
24766
25118
  payload.mode = mode;
24767
25119
  }
@@ -24769,11 +25121,11 @@ function buildCompileContextRequest(topicIdOrInput = {}, input = {}) {
24769
25121
  if (includeFailures !== void 0) {
24770
25122
  payload.includeFailures = includeFailures;
24771
25123
  }
24772
- const worktreeId = cleanString5(effectiveInput.worktreeId);
25124
+ const worktreeId = cleanString6(effectiveInput.worktreeId);
24773
25125
  if (worktreeId) {
24774
25126
  payload.worktreeId = worktreeId;
24775
25127
  }
24776
- const sessionId = cleanString5(effectiveInput.sessionId);
25128
+ const sessionId = cleanString6(effectiveInput.sessionId);
24777
25129
  if (sessionId) {
24778
25130
  payload.sessionId = sessionId;
24779
25131
  }
@@ -25782,6 +26134,7 @@ var FUNCTION_SURFACE_METHOD_PATHS = [
25782
26134
  "contracts.evaluateContract",
25783
26135
  "contracts.getContractStatus",
25784
26136
  "contradictions.flagContradiction",
26137
+ "controlPlane.identity.resolveInteractivePrincipal",
25785
26138
  "coordination.broadcastMessage",
25786
26139
  "coordination.claimFiles",
25787
26140
  "coordination.endSession",
@@ -25987,6 +26340,7 @@ var CONTRACTS = {
25987
26340
  "remove_edges_between": { method: "DELETE", path: "/edges/between", kind: "mutation", idempotent: true, surfaceIntent: "mcp_analysis" },
25988
26341
  "remove_lens_from_topic": { method: "DELETE", path: "/lenses/apply", kind: "mutation", idempotent: true, surfaceIntent: "mcp_workflow" },
25989
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" },
25990
26344
  "run_graph_intelligence_query": { method: "POST", path: "/graph-intelligence/run", kind: "query", idempotent: false, surfaceIntent: "mcp_analysis" },
25991
26345
  "search_beliefs": { method: "POST", path: "/beliefs/search", kind: "query", idempotent: false, surfaceIntent: "mcp_core" },
25992
26346
  "search_evidence": { method: "POST", path: "/evidence/search", kind: "query", idempotent: false, surfaceIntent: "mcp_core" },
@@ -26369,6 +26723,9 @@ function createFunctionSurfaceClient(config = {}) {
26369
26723
  resolveEffectiveOntology(input = {}, idempotencyKey) {
26370
26724
  return execute("resolve_effective_ontology", input, idempotencyKey);
26371
26725
  },
26726
+ resolveInteractivePrincipal(input = {}, idempotencyKey) {
26727
+ return execute("resolve_interactive_principal", input, idempotencyKey);
26728
+ },
26372
26729
  runGraphIntelligenceQuery(input = {}, idempotencyKey) {
26373
26730
  return execute("run_graph_intelligence_query", input, idempotencyKey);
26374
26731
  },
@@ -26629,7 +26986,7 @@ var ORG_GRAPH_SEARCH_FIELDS = [
26629
26986
  "cursor",
26630
26987
  "provenanceScope"
26631
26988
  ];
26632
- function cleanString6(value, label) {
26989
+ function cleanString7(value, label) {
26633
26990
  const normalized = value?.trim();
26634
26991
  if (!normalized) {
26635
26992
  throw new Error(`${label} is required`);
@@ -26651,9 +27008,9 @@ function searchBody(input) {
26651
27008
  "orgGraphSearch.search"
26652
27009
  );
26653
27010
  return {
26654
- tenantId: cleanString6(input.tenantId, "tenantId"),
26655
- workspaceId: cleanString6(input.workspaceId, "workspaceId"),
26656
- query: cleanString6(input.query, "query"),
27011
+ tenantId: cleanString7(input.tenantId, "tenantId"),
27012
+ workspaceId: cleanString7(input.workspaceId, "workspaceId"),
27013
+ query: cleanString7(input.query, "query"),
26657
27014
  nodeTypes: input.nodeTypes,
26658
27015
  minConfidence: input.minConfidence,
26659
27016
  limit: input.limit,
@@ -26663,8 +27020,8 @@ function searchBody(input) {
26663
27020
  }
26664
27021
  function listQuery2(input) {
26665
27022
  return {
26666
- tenantId: cleanString6(input.tenantId, "tenantId"),
26667
- workspaceId: cleanString6(input.workspaceId, "workspaceId"),
27023
+ tenantId: cleanString7(input.tenantId, "tenantId"),
27024
+ workspaceId: cleanString7(input.workspaceId, "workspaceId"),
26668
27025
  nodeTypes: input.nodeTypes?.join(","),
26669
27026
  minConfidence: input.minConfidence,
26670
27027
  limit: input.limit,
@@ -26698,8 +27055,8 @@ function createOrgGraphSearchClient(config = {}) {
26698
27055
  return gateway.request({
26699
27056
  path: `/api/platform/v1/org-graph-search/nodes/${nodePath}${toQueryString(
26700
27057
  {
26701
- tenantId: cleanString6(input.tenantId, "tenantId"),
26702
- workspaceId: cleanString6(input.workspaceId, "workspaceId"),
27058
+ tenantId: cleanString7(input.tenantId, "tenantId"),
27059
+ workspaceId: cleanString7(input.workspaceId, "workspaceId"),
26703
27060
  globalId: nodeId ? void 0 : globalId
26704
27061
  }
26705
27062
  )}`
@@ -27664,7 +28021,7 @@ function createToolRegistryClient(config = {}) {
27664
28021
  }
27665
28022
 
27666
28023
  // ../sdk/src/version.ts
27667
- var LUCERN_SDK_VERSION = "0.3.0-alpha.11";
28024
+ var LUCERN_SDK_VERSION = "0.3.0-alpha.13";
27668
28025
 
27669
28026
  // ../sdk/src/workflowClient.ts
27670
28027
  function normalizeLensQuery(value) {
@@ -28141,6 +28498,7 @@ function createLucernClient(config = {}) {
28141
28498
  const ontologyLinksClient = createOntologyLinksClient(gatewayConfig);
28142
28499
  const orgGraphSearchClient = createOrgGraphSearchClient(gatewayConfig);
28143
28500
  const functionSurfaceClient = createFunctionSurfaceClient(gatewayConfig);
28501
+ const controlPlaneClient = createControlPlaneClient(gatewayConfig);
28144
28502
  const toolRegistryClient = createToolRegistryClient(gatewayConfig);
28145
28503
  const modelRuntimeClient = createModelRuntimeClient(gatewayConfig);
28146
28504
  const packsClient = createPacksClient(gatewayConfig);
@@ -29804,9 +30162,16 @@ function createLucernClient(config = {}) {
29804
30162
  disable: packsClient.disable
29805
30163
  },
29806
30164
  nodes: nodesNamespace,
30165
+ controlPlane: {
30166
+ identity: {
30167
+ resolveInteractivePrincipal: controlPlaneClient.identity.resolveInteractivePrincipal
30168
+ },
30169
+ raw: controlPlaneClient
30170
+ },
29807
30171
  identity: {
29808
30172
  ...identityFacade,
29809
30173
  access: accessControlClient,
30174
+ resolveInteractivePrincipal: identityClient.resolveInteractivePrincipal,
29810
30175
  evaluatePolicy: identityClient.evaluatePolicy,
29811
30176
  recordPolicyDecision: identityClient.recordPolicyDecision,
29812
30177
  putSecretReference: identityClient.putSecretReference,
@@ -29851,6 +30216,7 @@ function createLucernClient(config = {}) {
29851
30216
  ontologyLinks: ontologyLinksClient,
29852
30217
  orgGraphSearch: orgGraphSearchClient,
29853
30218
  functionSurface: functionSurfaceClient,
30219
+ controlPlane: controlPlaneClient,
29854
30220
  toolRegistry: toolRegistryClient,
29855
30221
  modelRuntime: modelRuntimeClient,
29856
30222
  packs: packsClient,
@@ -29868,7 +30234,7 @@ function createLucernClient(config = {}) {
29868
30234
  }
29869
30235
 
29870
30236
  // ../sdk/src/facade/context.ts
29871
- function cleanString7(value) {
30237
+ function cleanString8(value) {
29872
30238
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
29873
30239
  }
29874
30240
  function cleanNumber2(value) {
@@ -29880,11 +30246,11 @@ function cleanBoolean2(value) {
29880
30246
  function buildCompileContextRequest2(topicIdOrInput = {}, input = {}) {
29881
30247
  const effectiveInput = typeof topicIdOrInput === "string" ? input : topicIdOrInput;
29882
30248
  const payload = {};
29883
- const topicId = typeof topicIdOrInput === "string" ? cleanString7(topicIdOrInput) : cleanString7(effectiveInput.topicId);
30249
+ const topicId = typeof topicIdOrInput === "string" ? cleanString8(topicIdOrInput) : cleanString8(effectiveInput.topicId);
29884
30250
  if (topicId) {
29885
30251
  payload.topicId = topicId;
29886
30252
  }
29887
- const query5 = cleanString7(effectiveInput.query);
30253
+ const query5 = cleanString8(effectiveInput.query);
29888
30254
  if (query5) {
29889
30255
  payload.query = query5;
29890
30256
  }
@@ -29892,7 +30258,7 @@ function buildCompileContextRequest2(topicIdOrInput = {}, input = {}) {
29892
30258
  if (budget !== void 0) {
29893
30259
  payload.budget = budget;
29894
30260
  }
29895
- const ranking = cleanString7(effectiveInput.ranking) ?? cleanString7(effectiveInput.rankingProfile);
30261
+ const ranking = cleanString8(effectiveInput.ranking) ?? cleanString8(effectiveInput.rankingProfile);
29896
30262
  if (ranking) {
29897
30263
  payload.ranking = ranking;
29898
30264
  }
@@ -29908,7 +30274,7 @@ function buildCompileContextRequest2(topicIdOrInput = {}, input = {}) {
29908
30274
  if (includeEntities !== void 0) {
29909
30275
  payload.includeEntities = includeEntities;
29910
30276
  }
29911
- const mode = cleanString7(effectiveInput.mode);
30277
+ const mode = cleanString8(effectiveInput.mode);
29912
30278
  if (mode) {
29913
30279
  payload.mode = mode;
29914
30280
  }
@@ -29916,11 +30282,11 @@ function buildCompileContextRequest2(topicIdOrInput = {}, input = {}) {
29916
30282
  if (includeFailures !== void 0) {
29917
30283
  payload.includeFailures = includeFailures;
29918
30284
  }
29919
- const worktreeId = cleanString7(effectiveInput.worktreeId);
30285
+ const worktreeId = cleanString8(effectiveInput.worktreeId);
29920
30286
  if (worktreeId) {
29921
30287
  payload.worktreeId = worktreeId;
29922
30288
  }
29923
- const sessionId = cleanString7(effectiveInput.sessionId);
30289
+ const sessionId = cleanString8(effectiveInput.sessionId);
29924
30290
  if (sessionId) {
29925
30291
  payload.sessionId = sessionId;
29926
30292
  }
@@ -31342,7 +31708,13 @@ var SESSION_AUTH_MODES = [
31342
31708
  "tenant_api_key",
31343
31709
  "session_token"
31344
31710
  ];
31345
- var SESSION_PRINCIPAL_TYPES = ["human", "service", "agent"];
31711
+ var SESSION_PRINCIPAL_TYPES = [
31712
+ "human",
31713
+ "service",
31714
+ "agent",
31715
+ "group",
31716
+ "external_viewer"
31717
+ ];
31346
31718
  var SESSION_LIFECYCLE_STATUSES = [
31347
31719
  "active",
31348
31720
  "expired",
@@ -31355,6 +31727,12 @@ function inferSessionPrincipalType(principalId) {
31355
31727
  if (principalId.startsWith("agent:")) {
31356
31728
  return "agent";
31357
31729
  }
31730
+ if (principalId.startsWith("group:")) {
31731
+ return "group";
31732
+ }
31733
+ if (principalId.startsWith("external:") || principalId.startsWith("external_viewer:")) {
31734
+ return "external_viewer";
31735
+ }
31358
31736
  return "service";
31359
31737
  }
31360
31738
  function normalizeDelegationChain(args) {
@@ -34570,7 +34948,7 @@ function createLucernStandaloneMcpServer(options) {
34570
34948
  });
34571
34949
  const server = new McpServer({
34572
34950
  name: "lucern-mcp",
34573
- version: "0.3.0-alpha.11"
34951
+ version: "0.3.0-alpha.13"
34574
34952
  });
34575
34953
  registerTools(server, runtime);
34576
34954
  const resources = registerResources(server, runtime, observationStore);