@lucern/contracts 0.3.0-alpha.2 → 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 (33) hide show
  1. package/dist/component-boundary.contract.d.ts +14 -0
  2. package/dist/component-boundary.contract.js +155 -0
  3. package/dist/component-boundary.contract.js.map +1 -0
  4. package/dist/gateway.contract.d.ts +1 -0
  5. package/dist/gateway.contract.js.map +1 -1
  6. package/dist/generated/convexSchemas.js +1 -0
  7. package/dist/generated/convexSchemas.js.map +1 -1
  8. package/dist/generated/schema-manifest.json +42 -3
  9. package/dist/generated/tableOwnership.d.ts +2 -1
  10. package/dist/generated/tableOwnership.js +2 -0
  11. package/dist/generated/tableOwnership.js.map +1 -1
  12. package/dist/generated/tier-expectations.json +4 -2
  13. package/dist/index.d.ts +258 -1
  14. package/dist/index.js +618 -1
  15. package/dist/index.js.map +1 -1
  16. package/dist/mcp-gateway-boundary.contract.d.ts +181 -0
  17. package/dist/mcp-gateway-boundary.contract.js +43 -0
  18. package/dist/mcp-gateway-boundary.contract.js.map +1 -0
  19. package/dist/schemas/component-table-manifest.d.ts +2 -2
  20. package/dist/schemas/index.js +35 -0
  21. package/dist/schemas/index.js.map +1 -1
  22. package/dist/schemas/manifest.d.ts +130 -20
  23. package/dist/schemas/manifest.js +35 -0
  24. package/dist/schemas/manifest.js.map +1 -1
  25. package/dist/schemas/tables/kernel/worktree.d.ts +2 -2
  26. package/dist/schemas/tables/mc/identity.d.ts +24 -1
  27. package/dist/schemas/tables/mc/identity.js +35 -1
  28. package/dist/schemas/tables/mc/identity.js.map +1 -1
  29. package/dist/schemas/tables/mc/pack.d.ts +2 -2
  30. package/dist/tenant-client.contract.d.ts +266 -0
  31. package/dist/tenant-client.contract.js +404 -0
  32. package/dist/tenant-client.contract.js.map +1 -0
  33. package/package.json +1 -1
@@ -0,0 +1,404 @@
1
+ // src/tenant-client.contract.ts
2
+ var TENANT_CLIENT_CONTRACT_VERSION = "2026-04-27";
3
+ var TENANT_CLIENT_AUTH_MODES = [
4
+ "interactive_user",
5
+ "service_principal",
6
+ "tenant_api_key",
7
+ "session_token"
8
+ ];
9
+ var TENANT_CLIENT_PRINCIPAL_TYPES = [
10
+ "human",
11
+ "service",
12
+ "agent"
13
+ ];
14
+ var TENANT_CLIENT_REQUIRED_CONTEXT_FIELDS = [
15
+ "tenantId",
16
+ "workspaceId",
17
+ "principalId",
18
+ "authMode",
19
+ "scopes"
20
+ ];
21
+ var TENANT_CLIENT_OPTIONAL_CONTEXT_FIELDS = [
22
+ "principalType",
23
+ "roles",
24
+ "sessionId",
25
+ "delegationChain"
26
+ ];
27
+ var TENANT_CLIENT_INSTALL_TOKEN_ENV = "INSTALL_LUCERN_NPM";
28
+ var TENANT_CLIENT_INSTALL_TOKEN_INFISICAL_PATH = "tenants/shared";
29
+ var TENANT_CLIENT_FORBIDDEN_INSTALL_TOKEN_INFISICAL_PATHS = [
30
+ "/platform/publish"
31
+ ];
32
+ var TENANT_CLIENT_FORBIDDEN_SECRET_ENV = ["NPM_TOKEN"];
33
+ var TENANT_CLIENT_INSTALLABLE_PACKAGES = [
34
+ {
35
+ packageName: "@lucern/access-control",
36
+ role: "sdk_dependency",
37
+ directTenantImport: false
38
+ },
39
+ {
40
+ packageName: "@lucern/agent",
41
+ role: "platform_runtime",
42
+ directTenantImport: false
43
+ },
44
+ {
45
+ packageName: "@lucern/auth",
46
+ role: "sdk_dependency",
47
+ directTenantImport: false
48
+ },
49
+ {
50
+ packageName: "@lucern/cli",
51
+ role: "developer_tool",
52
+ directTenantImport: false
53
+ },
54
+ {
55
+ packageName: "@lucern/client-core",
56
+ role: "sdk_dependency",
57
+ directTenantImport: false
58
+ },
59
+ {
60
+ packageName: "@lucern/confidence",
61
+ role: "sdk_dependency",
62
+ directTenantImport: false
63
+ },
64
+ {
65
+ packageName: "@lucern/config",
66
+ role: "configuration",
67
+ directTenantImport: false
68
+ },
69
+ {
70
+ packageName: "@lucern/contracts",
71
+ role: "contract_entrypoint",
72
+ directTenantImport: true
73
+ },
74
+ {
75
+ packageName: "@lucern/control-plane",
76
+ role: "platform_runtime",
77
+ directTenantImport: false
78
+ },
79
+ {
80
+ packageName: "@lucern/developer-kit",
81
+ role: "developer_tool",
82
+ directTenantImport: false
83
+ },
84
+ {
85
+ packageName: "@lucern/events",
86
+ role: "sdk_dependency",
87
+ directTenantImport: false
88
+ },
89
+ {
90
+ packageName: "@lucern/graph-primitives",
91
+ role: "sdk_dependency",
92
+ directTenantImport: false
93
+ },
94
+ {
95
+ packageName: "@lucern/identity",
96
+ role: "component_runtime",
97
+ directTenantImport: false
98
+ },
99
+ {
100
+ packageName: "@lucern/mcp",
101
+ role: "runtime_entrypoint",
102
+ directTenantImport: true
103
+ },
104
+ {
105
+ packageName: "@lucern/pack-host",
106
+ role: "platform_runtime",
107
+ directTenantImport: false
108
+ },
109
+ {
110
+ packageName: "@lucern/pack-installer",
111
+ role: "developer_tool",
112
+ directTenantImport: false
113
+ },
114
+ {
115
+ packageName: "@lucern/proof-compiler",
116
+ role: "developer_tool",
117
+ directTenantImport: false
118
+ },
119
+ {
120
+ packageName: "@lucern/react",
121
+ role: "runtime_entrypoint",
122
+ directTenantImport: true
123
+ },
124
+ {
125
+ packageName: "@lucern/reasoning-kernel",
126
+ role: "component_runtime",
127
+ directTenantImport: false
128
+ },
129
+ {
130
+ packageName: "@lucern/sdk",
131
+ role: "runtime_entrypoint",
132
+ directTenantImport: true
133
+ },
134
+ {
135
+ packageName: "@lucern/server-core",
136
+ role: "platform_runtime",
137
+ directTenantImport: false
138
+ },
139
+ {
140
+ packageName: "@lucern/testing",
141
+ role: "test_support",
142
+ directTenantImport: false
143
+ },
144
+ {
145
+ packageName: "@lucern/types",
146
+ role: "contract_entrypoint",
147
+ directTenantImport: true
148
+ }
149
+ ];
150
+ var TENANT_CLIENT_PUBLIC_IMPORTS = [
151
+ {
152
+ packageName: "@lucern/sdk",
153
+ surface: "runtime",
154
+ subpaths: "published_exports",
155
+ description: "TypeScript SDK runtime and generated operation namespaces."
156
+ },
157
+ {
158
+ packageName: "@lucern/react",
159
+ surface: "runtime",
160
+ subpaths: "published_exports",
161
+ description: "React bindings for tenant-owned UI applications."
162
+ },
163
+ {
164
+ packageName: "@lucern/mcp",
165
+ surface: "runtime",
166
+ subpaths: "published_exports",
167
+ description: "MCP client/server entry points and hosted route helpers."
168
+ },
169
+ {
170
+ packageName: "@lucern/contracts",
171
+ surface: "contract",
172
+ subpaths: "published_exports",
173
+ description: "Published type and manifest contracts."
174
+ },
175
+ {
176
+ packageName: "@lucern/types",
177
+ surface: "contract",
178
+ subpaths: "published_exports",
179
+ description: "Published type-only helpers for tenant integration code."
180
+ }
181
+ ];
182
+ var TENANT_CLIENT_COMPONENT_CONFIG_IMPORTS = [
183
+ {
184
+ packageName: "@lucern/identity",
185
+ importPath: "@lucern/identity/convex.config",
186
+ surface: "component_config",
187
+ description: "Convex component binding config for tenant deployments that install Lucern identity."
188
+ },
189
+ {
190
+ packageName: "@lucern/reasoning-kernel",
191
+ importPath: "@lucern/reasoning-kernel/convex.config",
192
+ surface: "component_config",
193
+ description: "Convex component binding config for tenant deployments that install the Lucern reasoning kernel."
194
+ },
195
+ {
196
+ packageName: "@lucern/reasoning-kernel",
197
+ importPath: "@lucern/reasoning-kernel/runtime.config",
198
+ surface: "component_config",
199
+ description: "Runtime config alias for tenant deployments that install the Lucern reasoning kernel."
200
+ }
201
+ ];
202
+ function findTenantClientInstallablePackage(packageName) {
203
+ return TENANT_CLIENT_INSTALLABLE_PACKAGES.find(
204
+ (entry) => entry.packageName === packageName
205
+ );
206
+ }
207
+ function isTenantClientInstallablePackage(packageName) {
208
+ return Boolean(findTenantClientInstallablePackage(packageName));
209
+ }
210
+ var TENANT_CLIENT_REQUIRED_SDK_NAMESPACES = [
211
+ "bootstrap",
212
+ "context",
213
+ "beliefs",
214
+ "evidence",
215
+ "questions",
216
+ "graph",
217
+ "worktrees",
218
+ "topics",
219
+ "edges",
220
+ "contradictions",
221
+ "contracts",
222
+ "graphAnalysis",
223
+ "graphRecommendations",
224
+ "orgGraphSearch",
225
+ "embeddings",
226
+ "ontologyLinks",
227
+ "graphStateClassifier",
228
+ "tools",
229
+ "identity",
230
+ "modelRuntime",
231
+ "events",
232
+ "jobs",
233
+ "telemetry"
234
+ ];
235
+ var TENANT_CLIENT_CAPABILITIES = [
236
+ {
237
+ id: "identity.bootstrap_session",
238
+ description: "Start a scoped Lucern session for a tenant principal.",
239
+ surfaces: ["@lucern/sdk", "@lucern/mcp"],
240
+ requiredContextFields: TENANT_CLIENT_REQUIRED_CONTEXT_FIELDS
241
+ },
242
+ {
243
+ id: "reasoning.context.compile",
244
+ description: "Compile tenant and workspace scoped reasoning context.",
245
+ surfaces: ["@lucern/sdk", "@lucern/react", "@lucern/mcp"],
246
+ requiredContextFields: TENANT_CLIENT_REQUIRED_CONTEXT_FIELDS
247
+ },
248
+ {
249
+ id: "reasoning.graph.read",
250
+ description: "Read beliefs, evidence, questions, topics, and lineage.",
251
+ surfaces: ["@lucern/sdk", "@lucern/react", "@lucern/mcp"],
252
+ requiredContextFields: TENANT_CLIENT_REQUIRED_CONTEXT_FIELDS
253
+ },
254
+ {
255
+ id: "reasoning.graph.write",
256
+ description: "Create and update graph objects through authorized APIs.",
257
+ surfaces: ["@lucern/sdk", "@lucern/mcp"],
258
+ requiredContextFields: TENANT_CLIENT_REQUIRED_CONTEXT_FIELDS
259
+ },
260
+ {
261
+ id: "workflow.worktree_lifecycle",
262
+ description: "Create, review, merge, and close scoped worktrees.",
263
+ surfaces: ["@lucern/sdk", "@lucern/react", "@lucern/mcp"],
264
+ requiredContextFields: TENANT_CLIENT_REQUIRED_CONTEXT_FIELDS
265
+ }
266
+ ];
267
+ var TENANT_CLIENT_ISOLATION_RULES = [
268
+ {
269
+ id: "tenant_workspace_scope_required",
270
+ description: "Runtime operations must resolve both tenantId and workspaceId before reaching Lucern reasoning state."
271
+ },
272
+ {
273
+ id: "principal_audit_required",
274
+ description: "Runtime operations must carry principalId, authMode, and scopes for audit attribution."
275
+ },
276
+ {
277
+ id: "no_private_lucern_imports",
278
+ description: "Tenant code must not import Lucern source, Convex internals, generated adapters, or unpublished package internals."
279
+ }
280
+ ];
281
+ var TENANT_CLIENT_FORBIDDEN_IMPORT_PATTERNS = [
282
+ {
283
+ id: "deep_src_import",
284
+ pattern: "^@lucern/[^/]+/src(?:/|$)",
285
+ description: "Published packages must not be bypassed through src paths."
286
+ },
287
+ {
288
+ id: "deep_dist_import",
289
+ pattern: "^@lucern/[^/]+/dist(?:/|$)",
290
+ description: "Published package exports must be used instead of dist file paths."
291
+ },
292
+ {
293
+ id: "generated_adapter_import",
294
+ pattern: "^@lucern/[^/]+/(?:adapters/)?_generated(?:/|$)",
295
+ description: "Generated Lucern adapters are internal deployment artifacts."
296
+ },
297
+ {
298
+ id: "private_runtime_import",
299
+ pattern: "^@lucern/[^/]+/(?:internal|private)(?:/|$)",
300
+ description: "Internal and private package subpaths are not public SDK API."
301
+ },
302
+ {
303
+ id: "workspace_source_import",
304
+ pattern: "^(?:packages|modules|services|lucern|apps)/(?:.+/)?src(?:/|$)",
305
+ description: "Tenant clients must not import source files from the Lucern monorepo."
306
+ },
307
+ {
308
+ id: "root_alias_lucern_import",
309
+ pattern: "^@/(?:lucern|packages|modules|services|apps)(?:/|$)",
310
+ description: "Tenant clients must not depend on Lucern repo-local path aliases."
311
+ },
312
+ {
313
+ id: "relative_lucern_source_import",
314
+ pattern: "^\\.\\.?/(?:.+/)?(?:packages|modules|services|lucern|apps)(?:/|$)",
315
+ description: "Tenant clients must not reach back into Lucern source through relative paths."
316
+ },
317
+ {
318
+ id: "monorepo_path_import",
319
+ pattern: "lucern-repo",
320
+ description: "Absolute imports that name the Lucern repository are not portable tenant code."
321
+ }
322
+ ];
323
+ function matchesPublicImport(importPath) {
324
+ const componentConfig = TENANT_CLIENT_COMPONENT_CONFIG_IMPORTS.find(
325
+ (entry) => importPath === entry.importPath
326
+ );
327
+ if (componentConfig) {
328
+ return componentConfig;
329
+ }
330
+ return TENANT_CLIENT_PUBLIC_IMPORTS.find(
331
+ (entry) => importPath === entry.packageName || importPath.startsWith(`${entry.packageName}/`)
332
+ );
333
+ }
334
+ function matchesForbiddenPattern(importPath) {
335
+ return TENANT_CLIENT_FORBIDDEN_IMPORT_PATTERNS.find(
336
+ (entry) => new RegExp(entry.pattern, "u").test(importPath)
337
+ );
338
+ }
339
+ function classifyTenantClientImport(importPath) {
340
+ const normalizedImportPath = importPath.trim();
341
+ const pattern = matchesForbiddenPattern(normalizedImportPath);
342
+ if (pattern) {
343
+ return {
344
+ importPath: normalizedImportPath,
345
+ decision: "forbidden",
346
+ pattern,
347
+ reason: pattern.description
348
+ };
349
+ }
350
+ const publicImport = matchesPublicImport(normalizedImportPath);
351
+ if (publicImport) {
352
+ return {
353
+ importPath: normalizedImportPath,
354
+ decision: "public",
355
+ publicImport,
356
+ reason: publicImport.description
357
+ };
358
+ }
359
+ if (normalizedImportPath.startsWith("@lucern/")) {
360
+ return {
361
+ importPath: normalizedImportPath,
362
+ decision: "forbidden",
363
+ reason: "This @lucern package is not part of the tenant client public surface."
364
+ };
365
+ }
366
+ if (normalizedImportPath.startsWith("./") || normalizedImportPath.startsWith("../")) {
367
+ return {
368
+ importPath: normalizedImportPath,
369
+ decision: "local",
370
+ reason: "Local tenant-owned import."
371
+ };
372
+ }
373
+ return {
374
+ importPath: normalizedImportPath,
375
+ decision: "external",
376
+ reason: "External dependency outside the Lucern package namespace."
377
+ };
378
+ }
379
+ function isTenantClientPublicImport(importPath) {
380
+ return classifyTenantClientImport(importPath).decision === "public";
381
+ }
382
+ function isTenantClientComponentConfigImport(importPath) {
383
+ return TENANT_CLIENT_COMPONENT_CONFIG_IMPORTS.some(
384
+ (entry) => importPath === entry.importPath
385
+ );
386
+ }
387
+ function isTenantClientAllowedImport(importPath) {
388
+ return classifyTenantClientImport(importPath).decision === "public";
389
+ }
390
+ function assertTenantClientImportAllowed(importPath) {
391
+ const classification = classifyTenantClientImport(importPath);
392
+ if (classification.decision !== "forbidden") {
393
+ return;
394
+ }
395
+ throw new Error(formatTenantClientImportViolation(classification));
396
+ }
397
+ function formatTenantClientImportViolation(classification) {
398
+ const patternId = classification.pattern ? ` [${classification.pattern.id}]` : "";
399
+ return `Tenant client import is not allowed${patternId}: ${classification.importPath}. ${classification.reason}`;
400
+ }
401
+
402
+ export { TENANT_CLIENT_AUTH_MODES, TENANT_CLIENT_CAPABILITIES, TENANT_CLIENT_COMPONENT_CONFIG_IMPORTS, TENANT_CLIENT_CONTRACT_VERSION, TENANT_CLIENT_FORBIDDEN_IMPORT_PATTERNS, TENANT_CLIENT_FORBIDDEN_INSTALL_TOKEN_INFISICAL_PATHS, TENANT_CLIENT_FORBIDDEN_SECRET_ENV, TENANT_CLIENT_INSTALLABLE_PACKAGES, TENANT_CLIENT_INSTALL_TOKEN_ENV, TENANT_CLIENT_INSTALL_TOKEN_INFISICAL_PATH, TENANT_CLIENT_ISOLATION_RULES, TENANT_CLIENT_OPTIONAL_CONTEXT_FIELDS, TENANT_CLIENT_PRINCIPAL_TYPES, TENANT_CLIENT_PUBLIC_IMPORTS, TENANT_CLIENT_REQUIRED_CONTEXT_FIELDS, TENANT_CLIENT_REQUIRED_SDK_NAMESPACES, assertTenantClientImportAllowed, classifyTenantClientImport, findTenantClientInstallablePackage, formatTenantClientImportViolation, isTenantClientAllowedImport, isTenantClientComponentConfigImport, isTenantClientInstallablePackage, isTenantClientPublicImport };
403
+ //# sourceMappingURL=tenant-client.contract.js.map
404
+ //# sourceMappingURL=tenant-client.contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/tenant-client.contract.ts"],"names":[],"mappings":"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","file":"tenant-client.contract.js","sourcesContent":["/**\n * Tenant client contract\n *\n * Defines the generic boundary for any customer-owned product that consumes\n * Lucern through the SDK, hosted API, or MCP server. Tenant clients may run\n * their own UI, auth provider, deployment, and data plane, but reasoning\n * operations must enter through the published packages below.\n */\n\nimport type {\n SessionAuthMode,\n SessionPrincipalType,\n} from \"./auth.contract\";\n\nexport const TENANT_CLIENT_CONTRACT_VERSION = \"2026-04-27\" as const;\n\nexport const TENANT_CLIENT_AUTH_MODES = [\n \"interactive_user\",\n \"service_principal\",\n \"tenant_api_key\",\n \"session_token\",\n] as const satisfies readonly SessionAuthMode[];\nexport type TenantClientAuthMode = (typeof TENANT_CLIENT_AUTH_MODES)[number];\n\nexport const TENANT_CLIENT_PRINCIPAL_TYPES = [\n \"human\",\n \"service\",\n \"agent\",\n] as const satisfies readonly SessionPrincipalType[];\nexport type TenantClientPrincipalType =\n (typeof TENANT_CLIENT_PRINCIPAL_TYPES)[number];\n\nexport const TENANT_CLIENT_REQUIRED_CONTEXT_FIELDS = [\n \"tenantId\",\n \"workspaceId\",\n \"principalId\",\n \"authMode\",\n \"scopes\",\n] as const;\nexport type TenantClientRequiredContextField =\n (typeof TENANT_CLIENT_REQUIRED_CONTEXT_FIELDS)[number];\n\nexport const TENANT_CLIENT_OPTIONAL_CONTEXT_FIELDS = [\n \"principalType\",\n \"roles\",\n \"sessionId\",\n \"delegationChain\",\n] as const;\nexport type TenantClientOptionalContextField =\n (typeof TENANT_CLIENT_OPTIONAL_CONTEXT_FIELDS)[number];\n\nexport const TENANT_CLIENT_INSTALL_TOKEN_ENV = \"INSTALL_LUCERN_NPM\" as const;\nexport const TENANT_CLIENT_INSTALL_TOKEN_INFISICAL_PATH =\n \"tenants/shared\" as const;\nexport const TENANT_CLIENT_FORBIDDEN_INSTALL_TOKEN_INFISICAL_PATHS = [\n \"/platform/publish\",\n] as const;\nexport const TENANT_CLIENT_FORBIDDEN_SECRET_ENV = [\"NPM_TOKEN\"] as const;\nexport type TenantClientForbiddenInstallTokenInfisicalPath =\n (typeof TENANT_CLIENT_FORBIDDEN_INSTALL_TOKEN_INFISICAL_PATHS)[number];\nexport type TenantClientForbiddenSecretEnv =\n (typeof TENANT_CLIENT_FORBIDDEN_SECRET_ENV)[number];\n\nexport const TENANT_CLIENT_INSTALLABLE_PACKAGES = [\n {\n packageName: \"@lucern/access-control\",\n role: \"sdk_dependency\",\n directTenantImport: false,\n },\n {\n packageName: \"@lucern/agent\",\n role: \"platform_runtime\",\n directTenantImport: false,\n },\n {\n packageName: \"@lucern/auth\",\n role: \"sdk_dependency\",\n directTenantImport: false,\n },\n {\n packageName: \"@lucern/cli\",\n role: \"developer_tool\",\n directTenantImport: false,\n },\n {\n packageName: \"@lucern/client-core\",\n role: \"sdk_dependency\",\n directTenantImport: false,\n },\n {\n packageName: \"@lucern/confidence\",\n role: \"sdk_dependency\",\n directTenantImport: false,\n },\n {\n packageName: \"@lucern/config\",\n role: \"configuration\",\n directTenantImport: false,\n },\n {\n packageName: \"@lucern/contracts\",\n role: \"contract_entrypoint\",\n directTenantImport: true,\n },\n {\n packageName: \"@lucern/control-plane\",\n role: \"platform_runtime\",\n directTenantImport: false,\n },\n {\n packageName: \"@lucern/developer-kit\",\n role: \"developer_tool\",\n directTenantImport: false,\n },\n {\n packageName: \"@lucern/events\",\n role: \"sdk_dependency\",\n directTenantImport: false,\n },\n {\n packageName: \"@lucern/graph-primitives\",\n role: \"sdk_dependency\",\n directTenantImport: false,\n },\n {\n packageName: \"@lucern/identity\",\n role: \"component_runtime\",\n directTenantImport: false,\n },\n {\n packageName: \"@lucern/mcp\",\n role: \"runtime_entrypoint\",\n directTenantImport: true,\n },\n {\n packageName: \"@lucern/pack-host\",\n role: \"platform_runtime\",\n directTenantImport: false,\n },\n {\n packageName: \"@lucern/pack-installer\",\n role: \"developer_tool\",\n directTenantImport: false,\n },\n {\n packageName: \"@lucern/proof-compiler\",\n role: \"developer_tool\",\n directTenantImport: false,\n },\n {\n packageName: \"@lucern/react\",\n role: \"runtime_entrypoint\",\n directTenantImport: true,\n },\n {\n packageName: \"@lucern/reasoning-kernel\",\n role: \"component_runtime\",\n directTenantImport: false,\n },\n {\n packageName: \"@lucern/sdk\",\n role: \"runtime_entrypoint\",\n directTenantImport: true,\n },\n {\n packageName: \"@lucern/server-core\",\n role: \"platform_runtime\",\n directTenantImport: false,\n },\n {\n packageName: \"@lucern/testing\",\n role: \"test_support\",\n directTenantImport: false,\n },\n {\n packageName: \"@lucern/types\",\n role: \"contract_entrypoint\",\n directTenantImport: true,\n },\n] as const;\nexport type TenantClientInstallablePackage =\n (typeof TENANT_CLIENT_INSTALLABLE_PACKAGES)[number];\nexport type TenantClientPackageRole = TenantClientInstallablePackage[\"role\"];\nexport type TenantClientInstallablePackageName =\n TenantClientInstallablePackage[\"packageName\"];\n\n/**\n * Direct imports tenant-owned product code may use. This is intentionally\n * smaller than TENANT_CLIENT_INSTALLABLE_PACKAGES: several publishable packages\n * are installed as SDK dependencies, tooling, or platform runtimes but should\n * not become the application integration surface.\n */\nexport const TENANT_CLIENT_PUBLIC_IMPORTS = [\n {\n packageName: \"@lucern/sdk\",\n surface: \"runtime\",\n subpaths: \"published_exports\",\n description: \"TypeScript SDK runtime and generated operation namespaces.\",\n },\n {\n packageName: \"@lucern/react\",\n surface: \"runtime\",\n subpaths: \"published_exports\",\n description: \"React bindings for tenant-owned UI applications.\",\n },\n {\n packageName: \"@lucern/mcp\",\n surface: \"runtime\",\n subpaths: \"published_exports\",\n description: \"MCP client/server entry points and hosted route helpers.\",\n },\n {\n packageName: \"@lucern/contracts\",\n surface: \"contract\",\n subpaths: \"published_exports\",\n description: \"Published type and manifest contracts.\",\n },\n {\n packageName: \"@lucern/types\",\n surface: \"contract\",\n subpaths: \"published_exports\",\n description: \"Published type-only helpers for tenant integration code.\",\n },\n] as const;\nexport type TenantClientPublicImport =\n (typeof TENANT_CLIENT_PUBLIC_IMPORTS)[number];\nexport type TenantClientPublicPackage =\n TenantClientPublicImport[\"packageName\"];\nexport type TenantClientPublicSurface = TenantClientPublicImport[\"surface\"];\n\nexport const TENANT_CLIENT_COMPONENT_CONFIG_IMPORTS = [\n {\n packageName: \"@lucern/identity\",\n importPath: \"@lucern/identity/convex.config\",\n surface: \"component_config\",\n description:\n \"Convex component binding config for tenant deployments that install Lucern identity.\",\n },\n {\n packageName: \"@lucern/reasoning-kernel\",\n importPath: \"@lucern/reasoning-kernel/convex.config\",\n surface: \"component_config\",\n description:\n \"Convex component binding config for tenant deployments that install the Lucern reasoning kernel.\",\n },\n {\n packageName: \"@lucern/reasoning-kernel\",\n importPath: \"@lucern/reasoning-kernel/runtime.config\",\n surface: \"component_config\",\n description:\n \"Runtime config alias for tenant deployments that install the Lucern reasoning kernel.\",\n },\n] as const;\nexport type TenantClientComponentConfigImport =\n (typeof TENANT_CLIENT_COMPONENT_CONFIG_IMPORTS)[number];\nexport type TenantClientAllowedImport =\n | TenantClientPublicImport\n | TenantClientComponentConfigImport;\n\nexport function findTenantClientInstallablePackage(\n packageName: string\n): TenantClientInstallablePackage | undefined {\n return TENANT_CLIENT_INSTALLABLE_PACKAGES.find(\n (entry) => entry.packageName === packageName\n );\n}\n\nexport function isTenantClientInstallablePackage(packageName: string): boolean {\n return Boolean(findTenantClientInstallablePackage(packageName));\n}\n\nexport const TENANT_CLIENT_REQUIRED_SDK_NAMESPACES = [\n \"bootstrap\",\n \"context\",\n \"beliefs\",\n \"evidence\",\n \"questions\",\n \"graph\",\n \"worktrees\",\n \"topics\",\n \"edges\",\n \"contradictions\",\n \"contracts\",\n \"graphAnalysis\",\n \"graphRecommendations\",\n \"orgGraphSearch\",\n \"embeddings\",\n \"ontologyLinks\",\n \"graphStateClassifier\",\n \"tools\",\n \"identity\",\n \"modelRuntime\",\n \"events\",\n \"jobs\",\n \"telemetry\",\n] as const;\nexport type TenantClientRequiredSdkNamespace =\n (typeof TENANT_CLIENT_REQUIRED_SDK_NAMESPACES)[number];\n\nexport const TENANT_CLIENT_CAPABILITIES = [\n {\n id: \"identity.bootstrap_session\",\n description: \"Start a scoped Lucern session for a tenant principal.\",\n surfaces: [\"@lucern/sdk\", \"@lucern/mcp\"],\n requiredContextFields: TENANT_CLIENT_REQUIRED_CONTEXT_FIELDS,\n },\n {\n id: \"reasoning.context.compile\",\n description: \"Compile tenant and workspace scoped reasoning context.\",\n surfaces: [\"@lucern/sdk\", \"@lucern/react\", \"@lucern/mcp\"],\n requiredContextFields: TENANT_CLIENT_REQUIRED_CONTEXT_FIELDS,\n },\n {\n id: \"reasoning.graph.read\",\n description: \"Read beliefs, evidence, questions, topics, and lineage.\",\n surfaces: [\"@lucern/sdk\", \"@lucern/react\", \"@lucern/mcp\"],\n requiredContextFields: TENANT_CLIENT_REQUIRED_CONTEXT_FIELDS,\n },\n {\n id: \"reasoning.graph.write\",\n description: \"Create and update graph objects through authorized APIs.\",\n surfaces: [\"@lucern/sdk\", \"@lucern/mcp\"],\n requiredContextFields: TENANT_CLIENT_REQUIRED_CONTEXT_FIELDS,\n },\n {\n id: \"workflow.worktree_lifecycle\",\n description: \"Create, review, merge, and close scoped worktrees.\",\n surfaces: [\"@lucern/sdk\", \"@lucern/react\", \"@lucern/mcp\"],\n requiredContextFields: TENANT_CLIENT_REQUIRED_CONTEXT_FIELDS,\n },\n] as const;\nexport type TenantClientCapability =\n (typeof TENANT_CLIENT_CAPABILITIES)[number];\nexport type TenantClientCapabilityId = TenantClientCapability[\"id\"];\n\nexport const TENANT_CLIENT_ISOLATION_RULES = [\n {\n id: \"tenant_workspace_scope_required\",\n description:\n \"Runtime operations must resolve both tenantId and workspaceId before reaching Lucern reasoning state.\",\n },\n {\n id: \"principal_audit_required\",\n description:\n \"Runtime operations must carry principalId, authMode, and scopes for audit attribution.\",\n },\n {\n id: \"no_private_lucern_imports\",\n description:\n \"Tenant code must not import Lucern source, Convex internals, generated adapters, or unpublished package internals.\",\n },\n] as const;\nexport type TenantClientIsolationRule =\n (typeof TENANT_CLIENT_ISOLATION_RULES)[number];\n\nexport const TENANT_CLIENT_FORBIDDEN_IMPORT_PATTERNS = [\n {\n id: \"deep_src_import\",\n pattern: \"^@lucern/[^/]+/src(?:/|$)\",\n description: \"Published packages must not be bypassed through src paths.\",\n },\n {\n id: \"deep_dist_import\",\n pattern: \"^@lucern/[^/]+/dist(?:/|$)\",\n description:\n \"Published package exports must be used instead of dist file paths.\",\n },\n {\n id: \"generated_adapter_import\",\n pattern: \"^@lucern/[^/]+/(?:adapters/)?_generated(?:/|$)\",\n description:\n \"Generated Lucern adapters are internal deployment artifacts.\",\n },\n {\n id: \"private_runtime_import\",\n pattern: \"^@lucern/[^/]+/(?:internal|private)(?:/|$)\",\n description: \"Internal and private package subpaths are not public SDK API.\",\n },\n {\n id: \"workspace_source_import\",\n pattern: \"^(?:packages|modules|services|lucern|apps)/(?:.+/)?src(?:/|$)\",\n description:\n \"Tenant clients must not import source files from the Lucern monorepo.\",\n },\n {\n id: \"root_alias_lucern_import\",\n pattern: \"^@/(?:lucern|packages|modules|services|apps)(?:/|$)\",\n description:\n \"Tenant clients must not depend on Lucern repo-local path aliases.\",\n },\n {\n id: \"relative_lucern_source_import\",\n pattern: \"^\\\\.\\\\.?/(?:.+/)?(?:packages|modules|services|lucern|apps)(?:/|$)\",\n description:\n \"Tenant clients must not reach back into Lucern source through relative paths.\",\n },\n {\n id: \"monorepo_path_import\",\n pattern: \"lucern-repo\",\n description:\n \"Absolute imports that name the Lucern repository are not portable tenant code.\",\n },\n] as const;\nexport type TenantClientForbiddenImportPattern =\n (typeof TENANT_CLIENT_FORBIDDEN_IMPORT_PATTERNS)[number];\nexport type TenantClientForbiddenImportPatternId =\n TenantClientForbiddenImportPattern[\"id\"];\n\nexport type TenantClientImportDecision =\n | \"public\"\n | \"forbidden\"\n | \"local\"\n | \"external\";\n\nexport type TenantClientImportClassification = {\n importPath: string;\n decision: TenantClientImportDecision;\n publicImport?: TenantClientAllowedImport;\n pattern?: TenantClientForbiddenImportPattern;\n reason: string;\n};\n\nfunction matchesPublicImport(\n importPath: string\n): TenantClientAllowedImport | undefined {\n const componentConfig = TENANT_CLIENT_COMPONENT_CONFIG_IMPORTS.find(\n (entry) => importPath === entry.importPath\n );\n if (componentConfig) {\n return componentConfig;\n }\n\n return TENANT_CLIENT_PUBLIC_IMPORTS.find(\n (entry) =>\n importPath === entry.packageName ||\n importPath.startsWith(`${entry.packageName}/`)\n );\n}\n\nfunction matchesForbiddenPattern(\n importPath: string\n): TenantClientForbiddenImportPattern | undefined {\n return TENANT_CLIENT_FORBIDDEN_IMPORT_PATTERNS.find((entry) =>\n new RegExp(entry.pattern, \"u\").test(importPath)\n );\n}\n\nexport function classifyTenantClientImport(\n importPath: string\n): TenantClientImportClassification {\n const normalizedImportPath = importPath.trim();\n const pattern = matchesForbiddenPattern(normalizedImportPath);\n\n if (pattern) {\n return {\n importPath: normalizedImportPath,\n decision: \"forbidden\",\n pattern,\n reason: pattern.description,\n };\n }\n\n const publicImport = matchesPublicImport(normalizedImportPath);\n if (publicImport) {\n return {\n importPath: normalizedImportPath,\n decision: \"public\",\n publicImport,\n reason: publicImport.description,\n };\n }\n\n if (normalizedImportPath.startsWith(\"@lucern/\")) {\n return {\n importPath: normalizedImportPath,\n decision: \"forbidden\",\n reason:\n \"This @lucern package is not part of the tenant client public surface.\",\n };\n }\n\n if (\n normalizedImportPath.startsWith(\"./\") ||\n normalizedImportPath.startsWith(\"../\")\n ) {\n return {\n importPath: normalizedImportPath,\n decision: \"local\",\n reason: \"Local tenant-owned import.\",\n };\n }\n\n return {\n importPath: normalizedImportPath,\n decision: \"external\",\n reason: \"External dependency outside the Lucern package namespace.\",\n };\n}\n\nexport function isTenantClientPublicImport(importPath: string): boolean {\n return classifyTenantClientImport(importPath).decision === \"public\";\n}\n\nexport function isTenantClientComponentConfigImport(\n importPath: string\n): boolean {\n return TENANT_CLIENT_COMPONENT_CONFIG_IMPORTS.some(\n (entry) => importPath === entry.importPath\n );\n}\n\nexport function isTenantClientAllowedImport(importPath: string): boolean {\n return classifyTenantClientImport(importPath).decision === \"public\";\n}\n\nexport function assertTenantClientImportAllowed(importPath: string): void {\n const classification = classifyTenantClientImport(importPath);\n if (classification.decision !== \"forbidden\") {\n return;\n }\n\n throw new Error(formatTenantClientImportViolation(classification));\n}\n\nexport function formatTenantClientImportViolation(\n classification: TenantClientImportClassification\n): string {\n const patternId = classification.pattern\n ? ` [${classification.pattern.id}]`\n : \"\";\n return `Tenant client import is not allowed${patternId}: ${classification.importPath}. ${classification.reason}`;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lucern/contracts",
3
- "version": "0.3.0-alpha.2",
3
+ "version": "0.3.0-alpha.3",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",