@lucern/sdk 0.3.0-alpha.1 → 0.3.0-alpha.10

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 (214) hide show
  1. package/CHANGELOG.md +3 -0
  2. package/README.md +51 -4
  3. package/dist/adminClient.d.ts +10 -8
  4. package/dist/adminClient.js +242 -39
  5. package/dist/adminClient.js.map +1 -1
  6. package/dist/answersClient.d.ts +2 -0
  7. package/dist/answersClient.js +221 -11
  8. package/dist/answersClient.js.map +1 -1
  9. package/dist/audience/index.d.ts +2 -1
  10. package/dist/audience/index.js +1 -3
  11. package/dist/audience/index.js.map +1 -1
  12. package/dist/audiencesClient.d.ts +18 -16
  13. package/dist/audiencesClient.js +297 -90
  14. package/dist/audiencesClient.js.map +1 -1
  15. package/dist/auditClient.d.ts +2 -0
  16. package/dist/auditClient.js +227 -15
  17. package/dist/auditClient.js.map +1 -1
  18. package/dist/authContext.d.ts +56 -0
  19. package/dist/authContext.js +170 -0
  20. package/dist/authContext.js.map +1 -0
  21. package/dist/authDeviceClient.d.ts +49 -0
  22. package/dist/authDeviceClient.js +121 -0
  23. package/dist/authDeviceClient.js.map +1 -0
  24. package/dist/beliefs/index.d.ts +25 -5
  25. package/dist/beliefs/index.js +3286 -1049
  26. package/dist/beliefs/index.js.map +1 -1
  27. package/dist/beliefsClient.d.ts +4 -2
  28. package/dist/beliefsClient.js +230 -26
  29. package/dist/beliefsClient.js.map +1 -1
  30. package/dist/boundaryClientSurface.d.ts +20 -0
  31. package/dist/boundaryClientSurface.js +73 -0
  32. package/dist/boundaryClientSurface.js.map +1 -0
  33. package/dist/client.d.ts +2969 -27
  34. package/dist/client.js +3286 -1049
  35. package/dist/client.js.map +1 -1
  36. package/dist/clientHelpers.d.ts +48 -0
  37. package/dist/clientHelpers.js +137 -0
  38. package/dist/clientHelpers.js.map +1 -0
  39. package/dist/contextClient.d.ts +6 -3
  40. package/dist/contextClient.js +252 -30
  41. package/dist/contextClient.js.map +1 -1
  42. package/dist/contextFacade.js +25 -16
  43. package/dist/contextFacade.js.map +1 -1
  44. package/dist/contextPackCompiler.js +19 -30
  45. package/dist/contextPackCompiler.js.map +1 -1
  46. package/dist/contextPackPolicy.js +7 -17
  47. package/dist/contextPackPolicy.js.map +1 -1
  48. package/dist/contextTypes.d.ts +2 -0
  49. package/dist/contracts/api-enums.contract.d.ts +1 -1
  50. package/dist/contracts/api-enums.contract.js.map +1 -1
  51. package/dist/contracts/index.d.ts +1 -0
  52. package/dist/contracts/index.js +108 -4
  53. package/dist/contracts/index.js.map +1 -1
  54. package/dist/contracts/lens-filter.contract.js +4 -3
  55. package/dist/contracts/lens-filter.contract.js.map +1 -1
  56. package/dist/contracts/lens-workflow.contract.js +4 -3
  57. package/dist/contracts/lens-workflow.contract.js.map +1 -1
  58. package/dist/contracts/lensFilter.js +4 -3
  59. package/dist/contracts/lensFilter.js.map +1 -1
  60. package/dist/contracts/lensWorkflow.js +4 -3
  61. package/dist/contracts/lensWorkflow.js.map +1 -1
  62. package/dist/contracts/mcpTools.d.ts +46 -1
  63. package/dist/contracts/mcpTools.js +102 -0
  64. package/dist/contracts/mcpTools.js.map +1 -1
  65. package/dist/contradictions/index.d.ts +24 -4
  66. package/dist/contradictions/index.js +3286 -1049
  67. package/dist/contradictions/index.js.map +1 -1
  68. package/dist/coreClient.d.ts +11 -1
  69. package/dist/coreClient.js +222 -14
  70. package/dist/coreClient.js.map +1 -1
  71. package/dist/decisions/index.d.ts +34 -14
  72. package/dist/decisions/index.js +3286 -1049
  73. package/dist/decisions/index.js.map +1 -1
  74. package/dist/decisionsClient.d.ts +6 -12
  75. package/dist/decisionsClient.js +235 -37
  76. package/dist/decisionsClient.js.map +1 -1
  77. package/dist/edges/index.d.ts +47 -87
  78. package/dist/edges/index.js +3286 -1049
  79. package/dist/edges/index.js.map +1 -1
  80. package/dist/embeddingsClient.d.ts +106 -0
  81. package/dist/embeddingsClient.js +731 -0
  82. package/dist/embeddingsClient.js.map +1 -0
  83. package/dist/eventingClient.d.ts +96 -0
  84. package/dist/eventingClient.js +728 -0
  85. package/dist/eventingClient.js.map +1 -0
  86. package/dist/events.js +6 -3
  87. package/dist/events.js.map +1 -1
  88. package/dist/eventsCore.d.ts +3 -1
  89. package/dist/eventsCore.js +222 -14
  90. package/dist/eventsCore.js.map +1 -1
  91. package/dist/evidence/index.d.ts +24 -4
  92. package/dist/evidence/index.js +3286 -1049
  93. package/dist/evidence/index.js.map +1 -1
  94. package/dist/evidenceClient.d.ts +2 -0
  95. package/dist/evidenceClient.js +222 -14
  96. package/dist/evidenceClient.js.map +1 -1
  97. package/dist/facade/context.d.ts +2 -1
  98. package/dist/facade/context.js +25 -16
  99. package/dist/facade/context.js.map +1 -1
  100. package/dist/functionSurface.d.ts +143 -0
  101. package/dist/functionSurface.js +1204 -0
  102. package/dist/functionSurface.js.map +1 -0
  103. package/dist/functionSurfaceClient.d.ts +8 -0
  104. package/dist/functionSurfaceClient.js +1204 -0
  105. package/dist/functionSurfaceClient.js.map +1 -0
  106. package/dist/gatewayFacades.d.ts +63 -46
  107. package/dist/gatewayFacades.js +461 -128
  108. package/dist/gatewayFacades.js.map +1 -1
  109. package/dist/graphAnalysisClient.d.ts +192 -0
  110. package/dist/graphAnalysisClient.js +799 -0
  111. package/dist/graphAnalysisClient.js.map +1 -0
  112. package/dist/graphClient.d.ts +7 -13
  113. package/dist/graphClient.js +244 -45
  114. package/dist/graphClient.js.map +1 -1
  115. package/dist/graphIntel.d.ts +3 -0
  116. package/dist/graphIntel.js +3 -0
  117. package/dist/graphIntel.js.map +1 -0
  118. package/dist/graphIntelligence.d.ts +2 -0
  119. package/dist/graphIntelligence.js +47 -0
  120. package/dist/graphIntelligence.js.map +1 -0
  121. package/dist/graphRecommendationsClient.d.ts +56 -0
  122. package/dist/graphRecommendationsClient.js +664 -0
  123. package/dist/graphRecommendationsClient.js.map +1 -0
  124. package/dist/graphStateClassifierClient.d.ts +73 -0
  125. package/dist/graphStateClassifierClient.js +716 -0
  126. package/dist/graphStateClassifierClient.js.map +1 -0
  127. package/dist/harnessClient.d.ts +15 -24
  128. package/dist/harnessClient.js +235 -42
  129. package/dist/harnessClient.js.map +1 -1
  130. package/dist/identityClient.d.ts +97 -11
  131. package/dist/identityClient.js +409 -33
  132. package/dist/identityClient.js.map +1 -1
  133. package/dist/index.d.ts +28 -5
  134. package/dist/index.js +3863 -1116
  135. package/dist/index.js.map +1 -1
  136. package/dist/infisicalRuntime.d.ts +42 -0
  137. package/dist/infisicalRuntime.js +314 -0
  138. package/dist/infisicalRuntime.js.map +1 -0
  139. package/dist/jobsClient.d.ts +98 -0
  140. package/dist/jobsClient.js +726 -0
  141. package/dist/jobsClient.js.map +1 -0
  142. package/dist/learningClient.d.ts +8 -6
  143. package/dist/learningClient.js +252 -44
  144. package/dist/learningClient.js.map +1 -1
  145. package/dist/lenses/index.d.ts +76 -38
  146. package/dist/lenses/index.js +3286 -1049
  147. package/dist/lenses/index.js.map +1 -1
  148. package/dist/mcpClient.d.ts +28 -0
  149. package/dist/mcpClient.js +668 -0
  150. package/dist/mcpClient.js.map +1 -0
  151. package/dist/modelRuntimeClient.d.ts +72 -0
  152. package/dist/modelRuntimeClient.js +704 -0
  153. package/dist/modelRuntimeClient.js.map +1 -0
  154. package/dist/nodes/index.d.ts +63 -21
  155. package/dist/nodes/index.js +3286 -1049
  156. package/dist/nodes/index.js.map +1 -1
  157. package/dist/ontologies/index.d.ts +53 -32
  158. package/dist/ontologies/index.js +3286 -1049
  159. package/dist/ontologies/index.js.map +1 -1
  160. package/dist/ontologyClient.d.ts +19 -25
  161. package/dist/ontologyClient.js +258 -40
  162. package/dist/ontologyClient.js.map +1 -1
  163. package/dist/ontologyLinksClient.d.ts +71 -0
  164. package/dist/ontologyLinksClient.js +697 -0
  165. package/dist/ontologyLinksClient.js.map +1 -0
  166. package/dist/orgGraphSearchClient.d.ts +85 -0
  167. package/dist/orgGraphSearchClient.js +672 -0
  168. package/dist/orgGraphSearchClient.js.map +1 -0
  169. package/dist/packsClient.d.ts +11 -23
  170. package/dist/packsClient.js +234 -46
  171. package/dist/packsClient.js.map +1 -1
  172. package/dist/policyClient.d.ts +13 -10
  173. package/dist/policyClient.js +243 -25
  174. package/dist/policyClient.js.map +1 -1
  175. package/dist/questions/index.d.ts +24 -4
  176. package/dist/questions/index.js +3286 -1049
  177. package/dist/questions/index.js.map +1 -1
  178. package/dist/realtime/index.d.ts +1 -1
  179. package/dist/reportsClient.d.ts +9 -7
  180. package/dist/reportsClient.js +281 -53
  181. package/dist/reportsClient.js.map +1 -1
  182. package/dist/schemaClient.d.ts +5 -3
  183. package/dist/schemaClient.js +235 -29
  184. package/dist/schemaClient.js.map +1 -1
  185. package/dist/sdkSurface.d.ts +8 -3
  186. package/dist/sdkSurface.js +10 -6
  187. package/dist/sdkSurface.js.map +1 -1
  188. package/dist/sourcesClient.d.ts +2 -0
  189. package/dist/sourcesClient.js +222 -14
  190. package/dist/sourcesClient.js.map +1 -1
  191. package/dist/telemetryClient.d.ts +94 -0
  192. package/dist/telemetryClient.js +741 -0
  193. package/dist/telemetryClient.js.map +1 -0
  194. package/dist/toolRegistryClient.d.ts +115 -0
  195. package/dist/toolRegistryClient.js +767 -0
  196. package/dist/toolRegistryClient.js.map +1 -0
  197. package/dist/topics/index.d.ts +35 -9
  198. package/dist/topics/index.js +3288 -1049
  199. package/dist/topics/index.js.map +1 -1
  200. package/dist/topicsClient.d.ts +4 -0
  201. package/dist/topicsClient.js +237 -24
  202. package/dist/topicsClient.js.map +1 -1
  203. package/dist/types.d.ts +5 -0
  204. package/dist/version.d.ts +1 -1
  205. package/dist/version.js +1 -1
  206. package/dist/version.js.map +1 -1
  207. package/dist/workflowClient.d.ts +58 -40
  208. package/dist/workflowClient.js +243 -58
  209. package/dist/workflowClient.js.map +1 -1
  210. package/dist/worktrees/index.d.ts +69 -33
  211. package/dist/worktrees/index.js +3286 -1049
  212. package/dist/worktrees/index.js.map +1 -1
  213. package/package.json +12 -3
  214. package/dist/client-B6aWUUwp.d.ts +0 -2552
@@ -1,5 +1,5 @@
1
1
  import { ConvexHttpClient } from 'convex/browser';
2
- import { useQuery, useMutation, useAction, useConvex, ConvexReactClient, ConvexReactClientOptions } from 'convex/react';
2
+ import { ConvexReactClient, ConvexReactClientOptions, useAction, useMutation, useConvex, useQuery } from 'convex/react';
3
3
  export { ConvexReactClientOptions as LucernConvexReactClientOptions } from 'convex/react';
4
4
  export { platformApi, subscriptionRefs } from './refs.js';
5
5
  export { AnyApi } from 'convex/server';
@@ -4,6 +4,8 @@ import { GatewayClientConfig, PlatformGatewaySuccess } from './coreClient.js';
4
4
  import './contracts/workflow-runtime.contract.js';
5
5
  import './contracts/lens-workflow.contract.js';
6
6
  import './contracts/lens-filter.contract.js';
7
+ import './authContext.js';
8
+ import './contracts/auth-session.contract.js';
7
9
 
8
10
  /** Configuration for the reports client. */
9
11
  type ReportsClientConfig = GatewayClientConfig;
@@ -17,25 +19,25 @@ declare function createReportsClient(config?: ReportsClientConfig): {
17
19
  /**
18
20
  * List report templates.
19
21
  */
20
- listTemplates(args?: {
22
+ listTemplates: (args?: {
21
23
  slug?: string;
22
- }): Promise<PlatformGatewaySuccess<ReportTemplatesResponse>>;
24
+ }) => Promise<PlatformGatewaySuccess<ReportTemplatesResponse>>;
23
25
  /**
24
26
  * @deprecated Use listTemplates.
25
27
  */
26
- getTemplates(args?: {
28
+ getTemplates: (args?: {
27
29
  slug?: string;
28
- }): Promise<PlatformGatewaySuccess<ReportTemplatesResponse>>;
30
+ }) => Promise<PlatformGatewaySuccess<ReportTemplatesResponse>>;
29
31
  /**
30
32
  * List reports for a topic scope.
31
33
  */
32
- listReports(input: TopicIdentifierInput, args?: {
34
+ listReports: (input: TopicIdentifierInput, args?: {
33
35
  summary?: boolean;
34
- }): Promise<PlatformGatewaySuccess<ListResult<any, "reports">>>;
36
+ }) => Promise<PlatformGatewaySuccess<ListResult<any, "reports">>>;
35
37
  /**
36
38
  * Get a generated report.
37
39
  */
38
- getReport(reportId: string): Promise<PlatformGatewaySuccess<ReportWithSectionsResponse>>;
40
+ getReport: (reportId: string) => Promise<PlatformGatewaySuccess<ReportWithSectionsResponse>>;
39
41
  };
40
42
 
41
43
  export { ReportTemplatesResponse, ReportWithSectionsResponse, type ReportsClientConfig, createReportsClient };
@@ -1,3 +1,170 @@
1
+ // src/authContext.ts
2
+ var LucernSdkAuthContextError = class extends Error {
3
+ reason;
4
+ constructor(reason, message) {
5
+ super(message);
6
+ this.name = "LucernSdkAuthContextError";
7
+ this.reason = reason;
8
+ }
9
+ };
10
+ function cleanString(value) {
11
+ const normalized = value?.trim();
12
+ return normalized ? normalized : void 0;
13
+ }
14
+ function cleanStringList(values) {
15
+ if (!values) {
16
+ return [];
17
+ }
18
+ return values.map((value) => value.trim()).filter(
19
+ (value, index, list) => value.length > 0 && list.indexOf(value) === index
20
+ );
21
+ }
22
+ function requireString(value, reason, label) {
23
+ const normalized = cleanString(value);
24
+ if (!normalized) {
25
+ throw new LucernSdkAuthContextError(
26
+ reason,
27
+ `Canonical Lucern SDK auth context is missing ${label}.`
28
+ );
29
+ }
30
+ return normalized;
31
+ }
32
+ function requirePrincipalType(principalType) {
33
+ if (!principalType) {
34
+ throw new LucernSdkAuthContextError(
35
+ "principal_missing",
36
+ "Canonical Lucern SDK auth context is missing principalType."
37
+ );
38
+ }
39
+ return principalType;
40
+ }
41
+ function requireAuthMode(authMode) {
42
+ if (!authMode) {
43
+ throw new LucernSdkAuthContextError(
44
+ "principal_missing",
45
+ "Canonical Lucern SDK auth context is missing authMode."
46
+ );
47
+ }
48
+ return authMode;
49
+ }
50
+ function ensurePermitMatch(args) {
51
+ const actual = cleanString(args.actual);
52
+ if (actual && actual !== args.expected) {
53
+ throw new LucernSdkAuthContextError(
54
+ "policy_denied",
55
+ `Canonical Lucern SDK auth context has conflicting Permit ${args.field}.`
56
+ );
57
+ }
58
+ }
59
+ function normalizeCanonicalLucernAuthContext(input) {
60
+ if (!input) {
61
+ throw new LucernSdkAuthContextError(
62
+ "principal_missing",
63
+ "Canonical Lucern SDK auth context is required."
64
+ );
65
+ }
66
+ if (input.policyDecision === "deny") {
67
+ throw new LucernSdkAuthContextError(
68
+ "policy_denied",
69
+ "Canonical Lucern SDK auth context carries a denied policy decision."
70
+ );
71
+ }
72
+ const principalId = requireString(
73
+ input.principalId,
74
+ "principal_missing",
75
+ "principalId"
76
+ );
77
+ const tenantId = requireString(input.tenantId, "tenant_missing", "tenantId");
78
+ const workspaceId = requireString(
79
+ input.workspaceId,
80
+ "workspace_missing",
81
+ "workspaceId"
82
+ );
83
+ const roles = cleanStringList(input.roles);
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) {
89
+ throw new LucernSdkAuthContextError(
90
+ "membership_missing",
91
+ "Canonical Lucern SDK auth context requires non-empty roles and scopes."
92
+ );
93
+ }
94
+ const subject = cleanString(input.permit?.subject) ?? principalId;
95
+ const tenant = cleanString(input.permit?.tenant) ?? tenantId;
96
+ const workspace = cleanString(input.permit?.workspace) ?? workspaceId;
97
+ ensurePermitMatch({
98
+ field: "subject",
99
+ expected: principalId,
100
+ actual: subject
101
+ });
102
+ ensurePermitMatch({ field: "tenant", expected: tenantId, actual: tenant });
103
+ ensurePermitMatch({
104
+ field: "workspace",
105
+ expected: workspaceId,
106
+ actual: workspace
107
+ });
108
+ const context = input.permit?.context ? { ...input.permit.context } : void 0;
109
+ return {
110
+ clerkId: cleanString(input.clerkId),
111
+ principalId,
112
+ tenantId,
113
+ workspaceId,
114
+ principalType,
115
+ authMode,
116
+ roles,
117
+ scopes,
118
+ delegationChain: input.delegationChain ? [...input.delegationChain] : [],
119
+ policyTraceId: cleanString(input.policyTraceId),
120
+ correlationId: cleanString(input.correlationId),
121
+ membershipId: cleanString(input.membershipId),
122
+ permit: {
123
+ subject,
124
+ tenant,
125
+ workspace,
126
+ resource: cleanString(input.permit?.resource),
127
+ action: cleanString(input.permit?.action),
128
+ relation: cleanString(input.permit?.relation),
129
+ context
130
+ }
131
+ };
132
+ }
133
+ function createCanonicalAuthHeaders(authContext) {
134
+ const headers = {
135
+ "x-lucern-principal-id": authContext.principalId,
136
+ "x-lucern-principal-type": authContext.principalType,
137
+ "x-lucern-tenant": authContext.tenantId,
138
+ "x-lucern-tenant-id": authContext.tenantId,
139
+ "x-lucern-workspace": authContext.workspaceId,
140
+ "x-lucern-workspace-id": authContext.workspaceId,
141
+ "x-lucern-auth-mode": authContext.authMode,
142
+ "x-lucern-roles": authContext.roles.join(","),
143
+ "x-lucern-scopes": authContext.scopes.join(","),
144
+ "x-lucern-permit-context": JSON.stringify(authContext.permit)
145
+ };
146
+ if (authContext.clerkId) {
147
+ headers["x-lucern-clerk-id"] = authContext.clerkId;
148
+ headers["x-lucern-user-id"] = authContext.clerkId;
149
+ }
150
+ if (authContext.delegationChain.length > 0) {
151
+ headers["x-lucern-delegation-chain"] = JSON.stringify(
152
+ authContext.delegationChain
153
+ );
154
+ }
155
+ if (authContext.policyTraceId) {
156
+ headers["x-lucern-policy-trace-id"] = authContext.policyTraceId;
157
+ }
158
+ if (authContext.correlationId) {
159
+ headers["x-correlation-id"] = authContext.correlationId;
160
+ headers["x-lucern-correlation-id"] = authContext.correlationId;
161
+ }
162
+ if (authContext.membershipId) {
163
+ headers["x-lucern-membership-id"] = authContext.membershipId;
164
+ }
165
+ return headers;
166
+ }
167
+
1
168
  // src/coreClient.ts
2
169
  var LucernApiError = class extends Error {
3
170
  code;
@@ -129,8 +296,11 @@ function timeoutError(timeoutMs) {
129
296
  error.name = "AbortError";
130
297
  return error;
131
298
  }
299
+ function isRecord(value) {
300
+ return value !== null && typeof value === "object" && !Array.isArray(value);
301
+ }
132
302
  function readPolicySummaryFromDetails(details) {
133
- if (!details || typeof details !== "object" || Array.isArray(details)) {
303
+ if (!isRecord(details)) {
134
304
  return null;
135
305
  }
136
306
  const directSummary = details.summary;
@@ -138,11 +308,11 @@ function readPolicySummaryFromDetails(details) {
138
308
  return directSummary.trim();
139
309
  }
140
310
  const policy = details.policy;
141
- if (!policy || typeof policy !== "object" || Array.isArray(policy)) {
311
+ if (!isRecord(policy)) {
142
312
  return null;
143
313
  }
144
314
  const explanation = policy.explanation;
145
- if (!explanation || typeof explanation !== "object" || Array.isArray(explanation)) {
315
+ if (!isRecord(explanation)) {
146
316
  return null;
147
317
  }
148
318
  const nestedSummary = explanation.summary;
@@ -151,16 +321,41 @@ function readPolicySummaryFromDetails(details) {
151
321
  }
152
322
  return null;
153
323
  }
324
+ async function resolveConfiguredAuthContext(authContext) {
325
+ if (typeof authContext === "function") {
326
+ return await authContext();
327
+ }
328
+ return authContext;
329
+ }
330
+ function mergeHeaderRecord(base, addition) {
331
+ const headers = new Headers(base);
332
+ for (const [key, value] of Object.entries(addition)) {
333
+ const existing = headers.get(key);
334
+ if (existing !== null && existing !== value) {
335
+ throw new LucernSdkAuthContextError(
336
+ "policy_denied",
337
+ `Canonical Lucern SDK auth context conflicts with existing ${key} header.`
338
+ );
339
+ }
340
+ headers.set(key, value);
341
+ }
342
+ return Object.fromEntries(headers.entries());
343
+ }
154
344
  function createGatewayRequestClient(config = {}) {
155
345
  const fetchImpl = config.fetchImpl ?? fetch;
156
346
  const baseUrl = config.baseUrl?.replace(/\/+$/, "") ?? "";
157
347
  const maxRetries = config.maxRetries ?? 2;
158
348
  const requestIdFactory = config.requestIdFactory ?? (() => generatePortableRequestId());
159
349
  async function resolveAuthHeaders() {
160
- if (!config.getAuthHeaders) {
161
- return {};
350
+ const base = config.getAuthHeaders ? await config.getAuthHeaders() : {};
351
+ const authContextInput = await resolveConfiguredAuthContext(
352
+ config.authContext
353
+ );
354
+ if (!authContextInput && !config.requireCanonicalAuthContext) {
355
+ return base;
162
356
  }
163
- return await config.getAuthHeaders();
357
+ const authContext = normalizeCanonicalLucernAuthContext(authContextInput);
358
+ return mergeHeaderRecord(base, createCanonicalAuthHeaders(authContext));
164
359
  }
165
360
  async function fetchWithTimeout(url, init, timeoutMs) {
166
361
  const controller = new AbortController();
@@ -181,11 +376,11 @@ function createGatewayRequestClient(config = {}) {
181
376
  if (!text) {
182
377
  return null;
183
378
  }
184
- try {
185
- return JSON.parse(text);
186
- } catch {
379
+ const parsed = tryParseGatewayEnvelopeJson(text);
380
+ if (!parsed.ok) {
187
381
  return null;
188
382
  }
383
+ return isRecord(parsed.value) ? parsed.value : null;
189
384
  }
190
385
  function resolveTimeoutMs(method, requestTimeoutMs) {
191
386
  if (typeof requestTimeoutMs === "number") {
@@ -197,16 +392,31 @@ function createGatewayRequestClient(config = {}) {
197
392
  }
198
393
  return config.timeoutMs ?? 15e3;
199
394
  }
395
+ function tryParseGatewayEnvelopeJson(text) {
396
+ const trimmed = text.trim();
397
+ if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) {
398
+ return { ok: false, reason: "non-json" };
399
+ }
400
+ try {
401
+ return { ok: true, value: JSON.parse(trimmed) };
402
+ } catch (error) {
403
+ if (error instanceof SyntaxError) {
404
+ return { ok: false, reason: "invalid-json", error };
405
+ }
406
+ throw error;
407
+ }
408
+ }
200
409
  function buildApiError(args) {
201
410
  const failure = args.failure;
202
- const legacyError = failure && typeof failure.error === "object" && failure.error !== null ? failure.error : failure?.legacyError;
411
+ const legacyError = failure && isRecord(failure.error) ? failure.error : failure?.legacyError;
203
412
  const correlationId = failure?.correlationId ?? args.response.headers.get("x-lucern-correlation-id")?.trim() ?? args.requestId;
204
413
  const policyTraceId = failure?.policyTraceId ?? args.response.headers.get("x-lucern-policy-trace-id")?.trim() ?? null;
205
414
  const details = failure?.details ?? legacyError?.details;
206
415
  const policySummary = readPolicySummaryFromDetails(details);
416
+ const failureMessage = typeof failure?.error === "string" ? failure.error : legacyError?.message;
207
417
  return new LucernApiError({
208
418
  code: failure?.code ?? legacyError?.code ?? fallbackErrorCode(args.response.status),
209
- message: policySummary ?? (typeof failure?.error === "string" ? failure.error : legacyError?.message ?? (args.response.ok ? "Platform API returned an invalid success payload." : "Platform API request failed.")),
419
+ message: policySummary ?? failureMessage ?? (args.response.ok ? "Platform API returned an invalid success payload." : "Platform API request failed."),
210
420
  status: args.response.status,
211
421
  invariant: failure?.invariant,
212
422
  suggestion: failure?.suggestion,
@@ -332,11 +542,30 @@ function createGatewayRequestClient(config = {}) {
332
542
  }
333
543
 
334
544
  // src/sdkSurface.ts
335
- function cleanString(value) {
545
+ function isRecord2(value) {
546
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
547
+ }
548
+ function asRecord(value) {
549
+ return isRecord2(value) ? value : {};
550
+ }
551
+ function cleanString2(value) {
336
552
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
337
553
  }
338
554
  function resolveTopicId(value) {
339
- return cleanString(value.topicId);
555
+ return cleanString2(value.topicId);
556
+ }
557
+ function asListItems(data, legacyKey) {
558
+ if (Array.isArray(data)) {
559
+ return data;
560
+ }
561
+ const record = asRecord(data);
562
+ if (Array.isArray(record.items)) {
563
+ return record.items;
564
+ }
565
+ if (Array.isArray(record[legacyKey])) {
566
+ return record[legacyKey];
567
+ }
568
+ return [];
340
569
  }
341
570
  function createListResult(items, legacyKey) {
342
571
  const result = {
@@ -344,7 +573,10 @@ function createListResult(items, legacyKey) {
344
573
  total: items.length
345
574
  };
346
575
  if (legacyKey) {
347
- result[legacyKey] = items;
576
+ return {
577
+ ...result,
578
+ [legacyKey]: items
579
+ };
348
580
  }
349
581
  return result;
350
582
  }
@@ -358,58 +590,54 @@ function mapGatewayData(response, mapper) {
358
590
  // src/reportsClient.ts
359
591
  function createReportsClient(config = {}) {
360
592
  const gateway = createGatewayRequestClient(config);
593
+ const listTemplates = async (args = {}) => gateway.request({
594
+ path: `/api/platform/v1/reports/templates${toQueryString({
595
+ slug: args.slug
596
+ })}`
597
+ }).then(
598
+ (response) => mapGatewayData(response, (data) => {
599
+ const rows = asListItems(data, "templates");
600
+ return createListResult(rows, "templates");
601
+ })
602
+ );
603
+ const listReports = async (input, args = {}) => {
604
+ const topicId = resolveTopicId(input);
605
+ if (!topicId) {
606
+ throw new Error("topicId is required");
607
+ }
608
+ return gateway.request({
609
+ path: `/api/platform/v1/reports/topics/${encodeURIComponent(topicId)}${toQueryString(
610
+ {
611
+ summary: typeof args.summary === "boolean" ? args.summary ? "true" : "false" : void 0
612
+ }
613
+ )}`
614
+ }).then(
615
+ (response) => mapGatewayData(
616
+ response,
617
+ (data) => createListResult(Array.isArray(data) ? data : [], "reports")
618
+ )
619
+ );
620
+ };
621
+ const getReport = async (reportId) => gateway.request({
622
+ path: `/api/platform/v1/reports/${encodeURIComponent(reportId)}`
623
+ });
361
624
  return {
362
625
  /**
363
626
  * List report templates.
364
627
  */
365
- async listTemplates(args = {}) {
366
- return gateway.request({
367
- path: `/api/platform/v1/reports/templates${toQueryString({
368
- slug: args.slug
369
- })}`
370
- }).then(
371
- (response) => mapGatewayData(response, (data) => {
372
- const record = data && typeof data === "object" ? data : {};
373
- const rows = Array.isArray(data) ? data : Array.isArray(record.templates) ? record.templates : [];
374
- return createListResult(rows, "templates");
375
- })
376
- );
377
- },
628
+ listTemplates,
378
629
  /**
379
630
  * @deprecated Use listTemplates.
380
631
  */
381
- async getTemplates(args = {}) {
382
- return this.listTemplates(args);
383
- },
632
+ getTemplates: listTemplates,
384
633
  /**
385
634
  * List reports for a topic scope.
386
635
  */
387
- async listReports(input, args = {}) {
388
- const topicId = resolveTopicId(input);
389
- if (!topicId) {
390
- throw new Error("topicId is required");
391
- }
392
- return gateway.request({
393
- path: `/api/platform/v1/reports/topics/${encodeURIComponent(topicId)}${toQueryString(
394
- {
395
- summary: typeof args.summary === "boolean" ? args.summary ? "true" : "false" : void 0
396
- }
397
- )}`
398
- }).then(
399
- (response) => mapGatewayData(
400
- response,
401
- (data) => createListResult(Array.isArray(data) ? data : [], "reports")
402
- )
403
- );
404
- },
636
+ listReports,
405
637
  /**
406
638
  * Get a generated report.
407
639
  */
408
- async getReport(reportId) {
409
- return gateway.request({
410
- path: `/api/platform/v1/reports/${encodeURIComponent(reportId)}`
411
- });
412
- }
640
+ getReport
413
641
  };
414
642
  }
415
643