@lucern/sdk 0.3.0-alpha.17 → 0.3.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (210) hide show
  1. package/CHANGELOG.md +0 -12
  2. package/README.md +4 -110
  3. package/dist/adminClient.d.ts +8 -8
  4. package/dist/adminClient.js +40 -70
  5. package/dist/adminClient.js.map +1 -1
  6. package/dist/answersClient.js +12 -49
  7. package/dist/answersClient.js.map +1 -1
  8. package/dist/audience/index.d.ts +1 -2
  9. package/dist/audience/index.js +3 -1
  10. package/dist/audience/index.js.map +1 -1
  11. package/dist/audiencesClient.d.ts +16 -16
  12. package/dist/audiencesClient.js +91 -125
  13. package/dist/audiencesClient.js.map +1 -1
  14. package/dist/auditClient.js +14 -53
  15. package/dist/auditClient.js.map +1 -1
  16. package/dist/authContext.d.ts +2 -2
  17. package/dist/authContext.js +3 -4
  18. package/dist/authContext.js.map +1 -1
  19. package/dist/authDeviceClient.js +3 -16
  20. package/dist/authDeviceClient.js.map +1 -1
  21. package/dist/beliefs/index.d.ts +4 -9
  22. package/dist/beliefs/index.js +1305 -1943
  23. package/dist/beliefs/index.js.map +1 -1
  24. package/dist/beliefsClient.d.ts +2 -2
  25. package/dist/beliefsClient.js +23 -54
  26. package/dist/beliefsClient.js.map +1 -1
  27. package/dist/boundaryClientSurface.js +3 -10
  28. package/dist/boundaryClientSurface.js.map +1 -1
  29. package/dist/client-EiG9nJOY.d.ts +2911 -0
  30. package/dist/client.d.ts +41 -3038
  31. package/dist/client.js +1305 -1943
  32. package/dist/client.js.map +1 -1
  33. package/dist/contextClient.d.ts +3 -4
  34. package/dist/contextClient.js +30 -79
  35. package/dist/contextClient.js.map +1 -1
  36. package/dist/contextFacade.js +16 -25
  37. package/dist/contextFacade.js.map +1 -1
  38. package/dist/contextPackCompiler.js +30 -19
  39. package/dist/contextPackCompiler.js.map +1 -1
  40. package/dist/contextPackPolicy.js +17 -7
  41. package/dist/contextPackPolicy.js.map +1 -1
  42. package/dist/contextTypes.d.ts +0 -2
  43. package/dist/contracts/api-enums.contract.d.ts +2 -2
  44. package/dist/contracts/api-enums.contract.js +1 -6
  45. package/dist/contracts/api-enums.contract.js.map +1 -1
  46. package/dist/contracts/auth-session.contract.d.ts +1 -1
  47. package/dist/contracts/auth-session.contract.js +2 -14
  48. package/dist/contracts/auth-session.contract.js.map +1 -1
  49. package/dist/contracts/index.js +6 -30
  50. package/dist/contracts/index.js.map +1 -1
  51. package/dist/contracts/lens-filter.contract.js +3 -4
  52. package/dist/contracts/lens-filter.contract.js.map +1 -1
  53. package/dist/contracts/lens-workflow.contract.js +3 -4
  54. package/dist/contracts/lens-workflow.contract.js.map +1 -1
  55. package/dist/contracts/lensFilter.js +3 -4
  56. package/dist/contracts/lensFilter.js.map +1 -1
  57. package/dist/contracts/lensWorkflow.js +3 -4
  58. package/dist/contracts/lensWorkflow.js.map +1 -1
  59. package/dist/contracts/mcpTools.js +0 -6
  60. package/dist/contracts/mcpTools.js.map +1 -1
  61. package/dist/contradictions/index.d.ts +3 -8
  62. package/dist/contradictions/index.js +1305 -1943
  63. package/dist/contradictions/index.js.map +1 -1
  64. package/dist/coreClient.d.ts +2 -19
  65. package/dist/coreClient.js +15 -50
  66. package/dist/coreClient.js.map +1 -1
  67. package/dist/decisions/index.d.ts +13 -18
  68. package/dist/decisions/index.js +1305 -1943
  69. package/dist/decisions/index.js.map +1 -1
  70. package/dist/decisionsClient.d.ts +12 -4
  71. package/dist/decisionsClient.js +35 -60
  72. package/dist/decisionsClient.js.map +1 -1
  73. package/dist/edges/index.d.ts +86 -31
  74. package/dist/edges/index.js +1305 -1943
  75. package/dist/edges/index.js.map +1 -1
  76. package/dist/embeddingsClient.js +18 -60
  77. package/dist/embeddingsClient.js.map +1 -1
  78. package/dist/eventingClient.js +18 -60
  79. package/dist/eventingClient.js.map +1 -1
  80. package/dist/events.js +3 -6
  81. package/dist/events.js.map +1 -1
  82. package/dist/eventsCore.d.ts +1 -1
  83. package/dist/eventsCore.js +15 -50
  84. package/dist/eventsCore.js.map +1 -1
  85. package/dist/evidence/index.d.ts +3 -8
  86. package/dist/evidence/index.js +1305 -1943
  87. package/dist/evidence/index.js.map +1 -1
  88. package/dist/evidenceClient.js +15 -50
  89. package/dist/evidenceClient.js.map +1 -1
  90. package/dist/facade/context.d.ts +1 -2
  91. package/dist/facade/context.js +16 -25
  92. package/dist/facade/context.js.map +1 -1
  93. package/dist/gatewayFacades.d.ts +48 -90
  94. package/dist/gatewayFacades.js +128 -251
  95. package/dist/gatewayFacades.js.map +1 -1
  96. package/dist/graphAnalysisClient.d.ts +1 -53
  97. package/dist/graphAnalysisClient.js +17 -81
  98. package/dist/graphAnalysisClient.js.map +1 -1
  99. package/dist/graphClient.d.ts +13 -6
  100. package/dist/graphClient.js +39 -65
  101. package/dist/graphClient.js.map +1 -1
  102. package/dist/graphRecommendationsClient.js +17 -54
  103. package/dist/graphRecommendationsClient.js.map +1 -1
  104. package/dist/graphStateClassifierClient.js +19 -60
  105. package/dist/graphStateClassifierClient.js.map +1 -1
  106. package/dist/harnessClient.d.ts +24 -13
  107. package/dist/harnessClient.js +41 -61
  108. package/dist/harnessClient.js.map +1 -1
  109. package/dist/identityClient.d.ts +9 -27
  110. package/dist/identityClient.js +39 -203
  111. package/dist/identityClient.js.map +1 -1
  112. package/dist/index.d.ts +6 -15
  113. package/dist/index.js +1171 -2256
  114. package/dist/index.js.map +1 -1
  115. package/dist/jobsClient.js +19 -60
  116. package/dist/jobsClient.js.map +1 -1
  117. package/dist/learningClient.d.ts +6 -6
  118. package/dist/learningClient.js +43 -78
  119. package/dist/learningClient.js.map +1 -1
  120. package/dist/lenses/index.d.ts +37 -60
  121. package/dist/lenses/index.js +1305 -1943
  122. package/dist/lenses/index.js.map +1 -1
  123. package/dist/mcpClient.js +13 -51
  124. package/dist/mcpClient.js.map +1 -1
  125. package/dist/modelRuntimeClient.js +18 -60
  126. package/dist/modelRuntimeClient.js.map +1 -1
  127. package/dist/nodes/index.d.ts +22 -49
  128. package/dist/nodes/index.js +1305 -1943
  129. package/dist/nodes/index.js.map +1 -1
  130. package/dist/ontologies/index.d.ts +31 -37
  131. package/dist/ontologies/index.js +1305 -1943
  132. package/dist/ontologies/index.js.map +1 -1
  133. package/dist/ontologyClient.d.ts +25 -17
  134. package/dist/ontologyClient.js +41 -86
  135. package/dist/ontologyClient.js.map +1 -1
  136. package/dist/ontologyLinksClient.js +19 -60
  137. package/dist/ontologyLinksClient.js.map +1 -1
  138. package/dist/orgGraphSearchClient.js +14 -53
  139. package/dist/orgGraphSearchClient.js.map +1 -1
  140. package/dist/packRuntime.d.ts +1 -2
  141. package/dist/packsClient.d.ts +23 -9
  142. package/dist/packsClient.js +47 -62
  143. package/dist/packsClient.js.map +1 -1
  144. package/dist/policyClient.d.ts +10 -11
  145. package/dist/policyClient.js +26 -71
  146. package/dist/policyClient.js.map +1 -1
  147. package/dist/questions/index.d.ts +3 -8
  148. package/dist/questions/index.js +1305 -1943
  149. package/dist/questions/index.js.map +1 -1
  150. package/dist/realtime/index.d.ts +1 -1
  151. package/dist/reportsClient.d.ts +7 -7
  152. package/dist/reportsClient.js +52 -107
  153. package/dist/reportsClient.js.map +1 -1
  154. package/dist/schemaClient.d.ts +3 -3
  155. package/dist/schemaClient.js +30 -63
  156. package/dist/schemaClient.js.map +1 -1
  157. package/dist/sdkSurface.d.ts +3 -6
  158. package/dist/sdkSurface.js +6 -10
  159. package/dist/sdkSurface.js.map +1 -1
  160. package/dist/sourcesClient.js +15 -50
  161. package/dist/sourcesClient.js.map +1 -1
  162. package/dist/telemetryClient.js +19 -60
  163. package/dist/telemetryClient.js.map +1 -1
  164. package/dist/toolRegistryClient.d.ts +2 -10
  165. package/dist/toolRegistryClient.js +20 -73
  166. package/dist/toolRegistryClient.js.map +1 -1
  167. package/dist/topics/index.d.ts +8 -19
  168. package/dist/topics/index.js +1305 -1945
  169. package/dist/topics/index.js.map +1 -1
  170. package/dist/topicsClient.d.ts +0 -2
  171. package/dist/topicsClient.js +20 -60
  172. package/dist/topicsClient.js.map +1 -1
  173. package/dist/types.d.ts +0 -17
  174. package/dist/version.d.ts +1 -1
  175. package/dist/version.js +1 -1
  176. package/dist/version.js.map +1 -1
  177. package/dist/workflowClient.d.ts +40 -58
  178. package/dist/workflowClient.js +54 -66
  179. package/dist/workflowClient.js.map +1 -1
  180. package/dist/worktrees/index.d.ts +33 -54
  181. package/dist/worktrees/index.js +1305 -1943
  182. package/dist/worktrees/index.js.map +1 -1
  183. package/package.json +3 -17
  184. package/dist/accessControl.d.ts +0 -79
  185. package/dist/accessControl.js +0 -1270
  186. package/dist/accessControl.js.map +0 -1
  187. package/dist/clientHelpers.d.ts +0 -48
  188. package/dist/clientHelpers.js +0 -137
  189. package/dist/clientHelpers.js.map +0 -1
  190. package/dist/control-plane.d.ts +0 -69
  191. package/dist/control-plane.js +0 -674
  192. package/dist/control-plane.js.map +0 -1
  193. package/dist/functionSurface.d.ts +0 -144
  194. package/dist/functionSurface.js +0 -1227
  195. package/dist/functionSurface.js.map +0 -1
  196. package/dist/functionSurfaceClient.d.ts +0 -8
  197. package/dist/functionSurfaceClient.js +0 -1227
  198. package/dist/functionSurfaceClient.js.map +0 -1
  199. package/dist/graphIntel.d.ts +0 -4
  200. package/dist/graphIntel.js +0 -3
  201. package/dist/graphIntel.js.map +0 -1
  202. package/dist/graphIntelligence.d.ts +0 -2
  203. package/dist/graphIntelligence.js +0 -47
  204. package/dist/graphIntelligence.js.map +0 -1
  205. package/dist/infisicalRuntime.d.ts +0 -43
  206. package/dist/infisicalRuntime.js +0 -346
  207. package/dist/infisicalRuntime.js.map +0 -1
  208. package/dist/secrets.d.ts +0 -1
  209. package/dist/secrets.js +0 -3
  210. package/dist/secrets.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -5,18 +5,6 @@ All notable changes to `@lucern/sdk` will be documented in this file.
5
5
  ## [Unreleased]
6
6
  - No unreleased changes yet.
7
7
 
8
- ## [0.3.0-alpha.17] - 2026-05-19
9
- - Release notes pending.
10
-
11
-
12
- ## [0.3.0-alpha.16] - 2026-05-14
13
- - Adds the exact-row reasoning-kernel migration surface required for tenant identity/scope repairs.
14
- - Keeps the coherent Lucern package line aligned for StackOS and reasoning-environment adoption.
15
-
16
-
17
- ## [0.3.0-alpha.7] - 2026-05-03
18
- - Rebuild the coherent Lucern package line after Campaign 1 SDK hardening fixes.
19
-
20
8
  ## [0.2.0-alpha.5] - 2026-04-18
21
9
  - Refresh publish from current stackos source under EK-16 T4.
22
10
  - Version-numbering note: 0.2.0-alpha.2 through 0.2.0-alpha.5 were published from earlier stackos source on 2026-04-12 by pete_c. This release (alpha.5) is the first to ship the current April 18 source — 56 commits of accumulated changes from the code-separation track.
package/README.md CHANGED
@@ -10,31 +10,6 @@ Lucern gives your agents a reasoning graph that accumulates understanding across
10
10
  npm install @lucern/sdk
11
11
  ```
12
12
 
13
- ## Install Model
14
-
15
- `@lucern/sdk` is the primary TypeScript app dependency. Installing it also
16
- installs its internal runtime dependencies, including Lucern contracts and
17
- reasoning-kernel helpers, but a tenant should still list any `@lucern/*`
18
- package that its own code or scripts import or execute.
19
-
20
- Common direct installs:
21
-
22
- | Need | Install |
23
- | --- | --- |
24
- | Programmatic Lucern API calls | `@lucern/sdk` |
25
- | Tool access checks | `@lucern/access-control` |
26
- | React hooks/components | `@lucern/react @lucern/sdk` |
27
- | Convex component binding | `@lucern/control-plane @lucern/reasoning-kernel` |
28
- | Bootstrap, auth, doctor, and operator commands | `@lucern/cli` |
29
- | Agent-facing MCP server/runtime | `@lucern/mcp` |
30
- | Full design-partner/package-suite pin | all packages from `TENANT_CLIENT_INSTALLABLE_PACKAGES` in `@lucern/contracts` |
31
-
32
- The difference matters: `@lucern/cli` is a direct install because it provides
33
- the `lucern` binary, but tenant app source should not import it. The Convex
34
- component packages are direct installs for `convex.config.ts`, while application
35
- code should stay on `@lucern/sdk`, `@lucern/react`, `@lucern/mcp`,
36
- `@lucern/access-control`, `@lucern/contracts`, and `@lucern/types`.
37
-
38
13
  ## Canonical Interface
39
14
 
40
15
  `@lucern/sdk` is the canonical public interface for Lucern.
@@ -42,9 +17,6 @@ code should stay on `@lucern/sdk`, `@lucern/react`, `@lucern/mcp`,
42
17
  - Build applications, automations, and backend integrations against the SDK first.
43
18
  - Treat `/api/platform/v1/*` as the transport mirror of the SDK surface.
44
19
  - Treat MCP as an agent-facing client of the same surface, not as a privileged bypass around SDK or HTTP semantics.
45
- - Treat REST, SDK, CLI, and MCP as projections of the same manifest. New
46
- control-plane operations must be added to the manifest first, then exposed
47
- through the generated surfaces.
48
20
 
49
21
  IA-7 closes the remaining SDK surface gaps needed for SDK-first clients:
50
22
 
@@ -70,62 +42,6 @@ const identity = await lucern.identity.whoami();
70
42
  const principal: SdkPrincipalContext = identity.data;
71
43
  ```
72
44
 
73
- ### Control-Plane Tenant Bootstrap
74
-
75
- Interactive tenant applications should resolve Clerk users through the Lucern
76
- control-plane identity surface before making workspace-scoped graph calls. Clerk
77
- proves the browser user's identity; Lucern authorization comes from the
78
- Permit-backed control-plane projection.
79
-
80
- ```typescript
81
- import { createLucernClient } from "@lucern/sdk";
82
-
83
- async function createLucernForClerkUser(args: {
84
- clerkUserId: string;
85
- getClerkToken: () => Promise<string | null>;
86
- tenantId: string;
87
- workspaceId: string;
88
- clerkProjectId?: string;
89
- }) {
90
- const token = await args.getClerkToken();
91
- if (!token) {
92
- throw new Error("Clerk session token is required.");
93
- }
94
-
95
- const getAuthHeaders = () => ({ Authorization: `Bearer ${token}` });
96
- const lucern = createLucernClient({
97
- baseUrl: "https://api.lucern.ai",
98
- getAuthHeaders,
99
- });
100
-
101
- const principal =
102
- await lucern.controlPlane.identity.resolveInteractivePrincipal({
103
- clerkId: args.clerkUserId,
104
- tenantId: args.tenantId,
105
- workspaceId: args.workspaceId,
106
- providerProjectId: args.clerkProjectId,
107
- });
108
-
109
- return createLucernClient({
110
- baseUrl: "https://api.lucern.ai",
111
- getAuthHeaders,
112
- authContext: principal.data,
113
- });
114
- }
115
- ```
116
-
117
- Use `authContext.principalId`, roles, scopes, groups, permitted tools, and
118
- Permit subject data as the runtime Lucern principal context. Tenant apps must
119
- not read legacy `users.mcRole` / `defaultTenantId` fields as authorization, and
120
- they must not call `components.controlPlane.migration` from application code.
121
- Provisioning and backfills can use migration APIs; runtime bootstrapping uses
122
- `controlPlane.identity.resolveInteractivePrincipal(...)`.
123
-
124
- StackOS, Lucern Graph, and Stack Engineering should use this bootstrap path
125
- before calling morning brief, graph session, MCP, or CLI-backed runtime flows.
126
- `/api/platform/v1/users/:clerkId` may be a profile facade, but it is not an
127
- authorization source.
128
-
129
45
  ## The Full Developer Journey
130
46
 
131
47
  This walkthrough mirrors what a developer building an AI-powered code review system would experience in a real coding session. Every API call is something you would actually use.
@@ -385,7 +301,7 @@ await lucern.graph.createEdge({
385
301
  Before your agent starts its next session, it reads the graph:
386
302
 
387
303
  ```typescript
388
- const context = await lucern.context.compile({
304
+ const context = await lucern.context.compile(topicId, {
389
305
  query: "code review strategy and static analysis coverage",
390
306
  ranking: "weighted_v1",
391
307
  tokenBudget: 2000,
@@ -447,28 +363,6 @@ lucern.identity // API keys and sessions
447
363
 
448
364
  The graph doesn't just store knowledge — it analyzes itself.
449
365
 
450
- ### Query Suite
451
-
452
- ```typescript
453
- // Discover the prompt-backed Graph Intelligence recipes tenants can expose in
454
- // their own UI or model workflows.
455
- const catalog = await lucern.graphAnalysis.listGraphIntelligenceQueries();
456
-
457
- // Run a named recipe. Lucern returns the resolved prompt, deterministic graph
458
- // analysis bundle, sampled graph context, and public tool plan for LLM synthesis.
459
- const preMortem = await lucern.graphAnalysis.runGraphIntelligenceQuery({
460
- topicId,
461
- queryId: "pre-mortem",
462
- limit: 25,
463
- });
464
-
465
- await modelMachine.run({
466
- prompt: preMortem.data.prompt,
467
- context: preMortem.data.analysis,
468
- tools: preMortem.data.toolPlan,
469
- });
470
- ```
471
-
472
366
  ### Structural Analysis
473
367
 
474
368
  ```typescript
@@ -551,7 +445,7 @@ traversal.data.nodes.forEach(node => {
551
445
  ### Inject Reasoning Context Into Any LLM Call
552
446
 
553
447
  ```typescript
554
- const context = await lucern.context.compile({
448
+ const context = await lucern.context.compile(topicId, {
555
449
  query: "security review priorities",
556
450
  ranking: "weighted_v1",
557
451
  tokenBudget: 3000,
@@ -662,7 +556,7 @@ architectural decisions, check the reasoning graph:
662
556
 
663
557
  - Read current beliefs: `lucern.beliefs.list({ topicId: "..." })`
664
558
  - Check for contradictions: `lucern.contradictions.list({ topicId: "..." })`
665
- - Compile context before analysis: `lucern.context.compile({ query: "..." })`
559
+ - Compile context before analysis: `lucern.context.compile(topicId, { query: "..." })`
666
560
 
667
561
  After making decisions, write them back:
668
562
  - Create beliefs for architectural decisions
@@ -693,7 +587,7 @@ contradictions, or knowledge state.
693
587
  Compile the current context to understand what the graph knows:
694
588
 
695
589
  \`\`\`typescript
696
- const context = await lucern.context.compile({
590
+ const context = await lucern.context.compile(topicId, {
697
591
  query: "<what you're working on>",
698
592
  tokenBudget: 2000,
699
593
  });
@@ -153,11 +153,11 @@ declare function createAdminClient(config?: AdminClientConfig): {
153
153
  /**
154
154
  * Get the control-object ownership contract.
155
155
  */
156
- getControlObjectOwnership: () => Promise<PlatformGatewaySuccess<ControlObjectOwnershipContract>>;
156
+ getControlObjectOwnership(): Promise<PlatformGatewaySuccess<ControlObjectOwnershipContract>>;
157
157
  /**
158
158
  * @deprecated Use getControlObjectOwnership.
159
159
  */
160
- getControlObjectOwnershipContract: () => Promise<PlatformGatewaySuccess<ControlObjectOwnershipContract>>;
160
+ getControlObjectOwnershipContract(): Promise<PlatformGatewaySuccess<ControlObjectOwnershipContract>>;
161
161
  /**
162
162
  * List workspaces for the current admin scope.
163
163
  */
@@ -190,33 +190,33 @@ declare function createAdminClient(config?: AdminClientConfig): {
190
190
  /**
191
191
  * Create a membership.
192
192
  */
193
- createMembership: (input: GatewayScope & {
193
+ createMembership(input: GatewayScope & {
194
194
  membershipId?: string;
195
195
  principalId: string;
196
196
  role: "platform_admin" | "tenant_admin" | "workspace_admin" | "editor" | "viewer" | "auditor" | "service_agent";
197
197
  status?: "active" | "invited" | "revoked" | "expired";
198
198
  source?: "bootstrap" | "manual" | "sync" | "sso" | "api" | "scim" | "invitation";
199
- }, idempotencyKey?: string) => Promise<PlatformGatewaySuccess<unknown>>;
199
+ }, idempotencyKey?: string): Promise<PlatformGatewaySuccess<unknown>>;
200
200
  /**
201
201
  * Update a membership.
202
202
  */
203
- updateMembership: (input: GatewayScope & {
203
+ updateMembership(input: GatewayScope & {
204
204
  membershipId?: string;
205
205
  principalId: string;
206
206
  role: "platform_admin" | "tenant_admin" | "workspace_admin" | "editor" | "viewer" | "auditor" | "service_agent";
207
207
  status?: "active" | "invited" | "revoked" | "expired";
208
208
  source?: "bootstrap" | "manual" | "sync" | "sso" | "api" | "scim" | "invitation";
209
- }, idempotencyKey?: string) => Promise<PlatformGatewaySuccess<unknown>>;
209
+ }, idempotencyKey?: string): Promise<PlatformGatewaySuccess<unknown>>;
210
210
  /**
211
211
  * @deprecated Use createMembership or updateMembership.
212
212
  */
213
- upsertMembership: (input: GatewayScope & {
213
+ upsertMembership(input: GatewayScope & {
214
214
  membershipId?: string;
215
215
  principalId: string;
216
216
  role: "platform_admin" | "tenant_admin" | "workspace_admin" | "editor" | "viewer" | "auditor" | "service_agent";
217
217
  status?: "active" | "invited" | "revoked" | "expired";
218
218
  source?: "bootstrap" | "manual" | "sync" | "sso" | "api" | "scim" | "invitation";
219
- }, idempotencyKey?: string) => Promise<PlatformGatewaySuccess<unknown>>;
219
+ }, idempotencyKey?: string): Promise<PlatformGatewaySuccess<unknown>>;
220
220
  /**
221
221
  * List tenant API keys in the current admin scope.
222
222
  */
@@ -82,15 +82,14 @@ function normalizeCanonicalLucernAuthContext(input) {
82
82
  );
83
83
  const roles = cleanStringList(input.roles);
84
84
  const scopes = cleanStringList(input.scopes);
85
- const principalType = requirePrincipalType(input.principalType);
86
- const authMode = requireAuthMode(input.authMode);
87
- const roleBasedInteractiveAuth = authMode === "interactive_user" && roles.length > 0;
88
- if (roles.length === 0 || scopes.length === 0 && !roleBasedInteractiveAuth) {
85
+ if (roles.length === 0 || scopes.length === 0) {
89
86
  throw new LucernSdkAuthContextError(
90
87
  "membership_missing",
91
88
  "Canonical Lucern SDK auth context requires non-empty roles and scopes."
92
89
  );
93
90
  }
91
+ const principalType = requirePrincipalType(input.principalType);
92
+ const authMode = requireAuthMode(input.authMode);
94
93
  const subject = cleanString(input.permit?.subject) ?? principalId;
95
94
  const tenant = cleanString(input.permit?.tenant) ?? tenantId;
96
95
  const workspace = cleanString(input.permit?.workspace) ?? workspaceId;
@@ -232,7 +231,9 @@ function generatePortableRequestId() {
232
231
  8
233
232
  ).join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10).join("")}`;
234
233
  }
235
- var randomIdempotencyKey = generatePortableRequestId;
234
+ function randomIdempotencyKey() {
235
+ return generatePortableRequestId();
236
+ }
236
237
  function isRetryableStatus(status) {
237
238
  return status >= 500 || status === 408 || status === 429;
238
239
  }
@@ -297,11 +298,8 @@ function timeoutError(timeoutMs) {
297
298
  error.name = "AbortError";
298
299
  return error;
299
300
  }
300
- function isRecord(value) {
301
- return value !== null && typeof value === "object" && !Array.isArray(value);
302
- }
303
301
  function readPolicySummaryFromDetails(details) {
304
- if (!isRecord(details)) {
302
+ if (!details || typeof details !== "object" || Array.isArray(details)) {
305
303
  return null;
306
304
  }
307
305
  const directSummary = details.summary;
@@ -309,11 +307,11 @@ function readPolicySummaryFromDetails(details) {
309
307
  return directSummary.trim();
310
308
  }
311
309
  const policy = details.policy;
312
- if (!isRecord(policy)) {
310
+ if (!policy || typeof policy !== "object" || Array.isArray(policy)) {
313
311
  return null;
314
312
  }
315
313
  const explanation = policy.explanation;
316
- if (!isRecord(explanation)) {
314
+ if (!explanation || typeof explanation !== "object" || Array.isArray(explanation)) {
317
315
  return null;
318
316
  }
319
317
  const nestedSummary = explanation.summary;
@@ -342,31 +340,13 @@ function mergeHeaderRecord(base, addition) {
342
340
  }
343
341
  return Object.fromEntries(headers.entries());
344
342
  }
345
- function cleanHeaderValue(value) {
346
- const normalized = value?.trim();
347
- return normalized ? normalized : void 0;
348
- }
349
343
  function createGatewayRequestClient(config = {}) {
350
344
  const fetchImpl = config.fetchImpl ?? fetch;
351
345
  const baseUrl = config.baseUrl?.replace(/\/+$/, "") ?? "";
352
346
  const maxRetries = config.maxRetries ?? 2;
353
347
  const requestIdFactory = config.requestIdFactory ?? (() => generatePortableRequestId());
354
348
  async function resolveAuthHeaders() {
355
- const provided = config.getAuthHeaders ? await config.getAuthHeaders() : {};
356
- const headers = new Headers(provided);
357
- const setIfAbsent = (name, value) => {
358
- const normalized = cleanHeaderValue(value);
359
- if (normalized && !headers.has(name)) {
360
- headers.set(name, normalized);
361
- }
362
- };
363
- setIfAbsent("x-lucern-key", config.apiKey);
364
- setIfAbsent("x-lucern-session-token", config.userToken);
365
- setIfAbsent("x-lucern-environment", config.environment);
366
- setIfAbsent("x-lucern-clerk-id", config.clerkId);
367
- setIfAbsent("x-lucern-user-id", config.userId ?? config.clerkId);
368
- setIfAbsent("x-lucern-deployment-host", config.deploymentHost);
369
- const base = Object.fromEntries(headers.entries());
349
+ const base = config.getAuthHeaders ? await config.getAuthHeaders() : {};
370
350
  const authContextInput = await resolveConfiguredAuthContext(
371
351
  config.authContext
372
352
  );
@@ -395,11 +375,11 @@ function createGatewayRequestClient(config = {}) {
395
375
  if (!text) {
396
376
  return null;
397
377
  }
398
- const parsed = tryParseGatewayEnvelopeJson(text);
399
- if (!parsed.ok) {
378
+ try {
379
+ return JSON.parse(text);
380
+ } catch {
400
381
  return null;
401
382
  }
402
- return isRecord(parsed.value) ? parsed.value : null;
403
383
  }
404
384
  function resolveTimeoutMs(method, requestTimeoutMs) {
405
385
  if (typeof requestTimeoutMs === "number") {
@@ -411,31 +391,16 @@ function createGatewayRequestClient(config = {}) {
411
391
  }
412
392
  return config.timeoutMs ?? 15e3;
413
393
  }
414
- function tryParseGatewayEnvelopeJson(text) {
415
- const trimmed = text.trim();
416
- if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) {
417
- return { ok: false, reason: "non-json" };
418
- }
419
- try {
420
- return { ok: true, value: JSON.parse(trimmed) };
421
- } catch (error) {
422
- if (error instanceof SyntaxError) {
423
- return { ok: false, reason: "invalid-json", error };
424
- }
425
- throw error;
426
- }
427
- }
428
394
  function buildApiError(args) {
429
395
  const failure = args.failure;
430
- const legacyError = failure && isRecord(failure.error) ? failure.error : failure?.legacyError;
396
+ const legacyError = failure && typeof failure.error === "object" && failure.error !== null ? failure.error : failure?.legacyError;
431
397
  const correlationId = failure?.correlationId ?? args.response.headers.get("x-lucern-correlation-id")?.trim() ?? args.requestId;
432
398
  const policyTraceId = failure?.policyTraceId ?? args.response.headers.get("x-lucern-policy-trace-id")?.trim() ?? null;
433
399
  const details = failure?.details ?? legacyError?.details;
434
400
  const policySummary = readPolicySummaryFromDetails(details);
435
- const failureMessage = typeof failure?.error === "string" ? failure.error : legacyError?.message;
436
401
  return new LucernApiError({
437
402
  code: failure?.code ?? legacyError?.code ?? fallbackErrorCode(args.response.status),
438
- message: policySummary ?? failureMessage ?? (args.response.ok ? "Platform API returned an invalid success payload." : "Platform API request failed."),
403
+ message: policySummary ?? (typeof failure?.error === "string" ? failure.error : legacyError?.message ?? (args.response.ok ? "Platform API returned an invalid success payload." : "Platform API request failed.")),
439
404
  status: args.response.status,
440
405
  invariant: failure?.invariant,
441
406
  suggestion: failure?.suggestion,
@@ -567,10 +532,7 @@ function createListResult(items, legacyKey) {
567
532
  total: items.length
568
533
  };
569
534
  if (legacyKey) {
570
- return {
571
- ...result,
572
- [legacyKey]: items
573
- };
535
+ result[legacyKey] = items;
574
536
  }
575
537
  return result;
576
538
  }
@@ -608,17 +570,6 @@ function asTenantVaultSecretArray(data) {
608
570
  }
609
571
  function createAdminClient(config = {}) {
610
572
  const gateway = createGatewayRequestClient(config);
611
- const getControlObjectOwnership = async () => gateway.request({
612
- path: "/api/platform/v1/admin/control-ownership"
613
- });
614
- const createMembership = async (input, idempotencyKey) => gateway.request({
615
- path: "/api/platform/v1/memberships",
616
- method: "POST",
617
- body: input,
618
- idempotencyKey: idempotencyKey ?? randomIdempotencyKey()
619
- });
620
- const updateMembership = createMembership;
621
- const upsertMembership = createMembership;
622
573
  return {
623
574
  /**
624
575
  * List tenants visible to the current principal.
@@ -650,11 +601,19 @@ function createAdminClient(config = {}) {
650
601
  /**
651
602
  * Get the control-object ownership contract.
652
603
  */
653
- getControlObjectOwnership,
604
+ async getControlObjectOwnership() {
605
+ return gateway.request({
606
+ path: "/api/platform/v1/admin/control-ownership"
607
+ });
608
+ },
654
609
  /**
655
610
  * @deprecated Use getControlObjectOwnership.
656
611
  */
657
- getControlObjectOwnershipContract: getControlObjectOwnership,
612
+ async getControlObjectOwnershipContract() {
613
+ return gateway.request({
614
+ path: "/api/platform/v1/admin/control-ownership"
615
+ });
616
+ },
658
617
  /**
659
618
  * List workspaces for the current admin scope.
660
619
  */
@@ -701,15 +660,26 @@ function createAdminClient(config = {}) {
701
660
  /**
702
661
  * Create a membership.
703
662
  */
704
- createMembership,
663
+ async createMembership(input, idempotencyKey) {
664
+ return gateway.request({
665
+ path: "/api/platform/v1/memberships",
666
+ method: "POST",
667
+ body: input,
668
+ idempotencyKey: idempotencyKey ?? randomIdempotencyKey()
669
+ });
670
+ },
705
671
  /**
706
672
  * Update a membership.
707
673
  */
708
- updateMembership,
674
+ async updateMembership(input, idempotencyKey) {
675
+ return this.createMembership(input, idempotencyKey);
676
+ },
709
677
  /**
710
678
  * @deprecated Use createMembership or updateMembership.
711
679
  */
712
- upsertMembership,
680
+ async upsertMembership(input, idempotencyKey) {
681
+ return this.createMembership(input, idempotencyKey);
682
+ },
713
683
  /**
714
684
  * List tenant API keys in the current admin scope.
715
685
  */