ltcai 1.0.1 → 1.2.0
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/README.md +34 -0
- package/docs/CHANGELOG.md +99 -0
- package/docs/EDITION_STRATEGY.md +56 -0
- package/docs/ENTERPRISE.md +78 -0
- package/latticeai/__init__.py +1 -1
- package/latticeai/api/health.py +45 -0
- package/latticeai/api/workspace.py +748 -0
- package/latticeai/core/enterprise.py +152 -0
- package/latticeai/core/workspace_os.py +409 -38
- package/latticeai/server_app.py +73 -530
- package/latticeai/services/__init__.py +6 -0
- package/latticeai/services/chat_service.py +53 -0
- package/latticeai/services/model_service.py +51 -0
- package/latticeai/services/workspace_service.py +117 -0
- package/package.json +1 -1
- package/static/scripts/workspace.js +149 -0
- package/static/sw.js +1 -1
- package/static/workspace.css +31 -0
- package/static/workspace.html +41 -2
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"""Enterprise extension seam (open-core boundary).
|
|
2
|
+
|
|
3
|
+
LatticeAI Community is fully functional on its own. This module defines the
|
|
4
|
+
*seam* where a future, separately-distributed Enterprise plugin can attach
|
|
5
|
+
advanced capabilities (SSO provisioning, SCIM, tenant isolation, compliance
|
|
6
|
+
retention, SIEM export, and so on) **without** any of that code living in the
|
|
7
|
+
public Community repository.
|
|
8
|
+
|
|
9
|
+
Design rules enforced here:
|
|
10
|
+
|
|
11
|
+
* Community is the default :class:`Edition`. Every :class:`EnterpriseCapability`
|
|
12
|
+
is **disabled** unless an Enterprise provider is explicitly registered.
|
|
13
|
+
* Nothing in this module restricts or gates a Community feature. It only answers
|
|
14
|
+
"is this *Enterprise* capability available?" — which is ``False`` in the open
|
|
15
|
+
build.
|
|
16
|
+
* Enterprise behaviour is supplied at runtime through
|
|
17
|
+
:class:`CapabilityProvider` implementations registered on the shared
|
|
18
|
+
:data:`capability_registry`. The public code never imports Enterprise code.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
import os
|
|
24
|
+
from enum import Enum
|
|
25
|
+
from typing import Dict, List, Optional, Protocol, runtime_checkable
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class Edition(str, Enum):
|
|
29
|
+
"""Distribution edition. Community is the open-source default."""
|
|
30
|
+
|
|
31
|
+
COMMUNITY = "community"
|
|
32
|
+
ENTERPRISE = "enterprise"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class EnterpriseCapability(str, Enum):
|
|
36
|
+
"""Capabilities reserved for the Enterprise edition.
|
|
37
|
+
|
|
38
|
+
These are documented in ``docs/ENTERPRISE.md``. They are intentionally
|
|
39
|
+
declared (so the seam is stable and discoverable) but never implemented in
|
|
40
|
+
the Community build.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
SSO_ADVANCED = "sso_advanced"
|
|
44
|
+
IDP_PROVISIONING = "idp_provisioning" # Entra ID / Okta provisioning
|
|
45
|
+
SCIM = "scim"
|
|
46
|
+
RBAC_ABAC_ADVANCED = "rbac_abac_advanced"
|
|
47
|
+
TENANT_ISOLATION = "tenant_isolation"
|
|
48
|
+
COMPLIANCE_RETENTION = "compliance_retention"
|
|
49
|
+
SIEM_EXPORT = "siem_export"
|
|
50
|
+
PRIVATE_VPC = "private_vpc"
|
|
51
|
+
AIR_GAPPED_DEPLOYMENT = "air_gapped_deployment"
|
|
52
|
+
DLP_POLICY = "dlp_policy"
|
|
53
|
+
EDISCOVERY = "ediscovery"
|
|
54
|
+
ADMIN_POLICY_PACKS = "admin_policy_packs"
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@runtime_checkable
|
|
58
|
+
class CapabilityProvider(Protocol):
|
|
59
|
+
"""Contract an Enterprise plugin implements to light up capabilities.
|
|
60
|
+
|
|
61
|
+
A provider is registered at runtime via
|
|
62
|
+
:meth:`CapabilityRegistry.register_provider`. The Community build ships no
|
|
63
|
+
provider, so :meth:`is_enabled` is effectively ``False`` everywhere.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
def edition(self) -> Edition:
|
|
67
|
+
...
|
|
68
|
+
|
|
69
|
+
def is_enabled(self, capability: EnterpriseCapability) -> bool:
|
|
70
|
+
...
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class CommunityCapabilityProvider:
|
|
74
|
+
"""Default provider: Community edition, no Enterprise capabilities."""
|
|
75
|
+
|
|
76
|
+
def edition(self) -> Edition:
|
|
77
|
+
return Edition.COMMUNITY
|
|
78
|
+
|
|
79
|
+
def is_enabled(self, capability: EnterpriseCapability) -> bool: # noqa: ARG002
|
|
80
|
+
return False
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class CapabilityRegistry:
|
|
84
|
+
"""Runtime seam that an Enterprise plugin can attach a provider to.
|
|
85
|
+
|
|
86
|
+
The registry holds at most one active provider. Until an Enterprise build
|
|
87
|
+
registers one, the :class:`CommunityCapabilityProvider` answers every query
|
|
88
|
+
with "Community / disabled".
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
def __init__(self) -> None:
|
|
92
|
+
self._provider: CapabilityProvider = CommunityCapabilityProvider()
|
|
93
|
+
|
|
94
|
+
def register_provider(self, provider: CapabilityProvider) -> None:
|
|
95
|
+
if not isinstance(provider, CapabilityProvider):
|
|
96
|
+
raise TypeError("provider must implement the CapabilityProvider protocol")
|
|
97
|
+
self._provider = provider
|
|
98
|
+
|
|
99
|
+
def reset(self) -> None:
|
|
100
|
+
"""Restore the Community default provider (used by tests)."""
|
|
101
|
+
self._provider = CommunityCapabilityProvider()
|
|
102
|
+
|
|
103
|
+
def edition(self) -> Edition:
|
|
104
|
+
return self._provider.edition()
|
|
105
|
+
|
|
106
|
+
def is_capability_enabled(self, capability: EnterpriseCapability) -> bool:
|
|
107
|
+
try:
|
|
108
|
+
return bool(self._provider.is_enabled(capability))
|
|
109
|
+
except Exception:
|
|
110
|
+
# A misbehaving plugin must never break a Community request.
|
|
111
|
+
return False
|
|
112
|
+
|
|
113
|
+
def available_capabilities(self) -> List[EnterpriseCapability]:
|
|
114
|
+
return [cap for cap in EnterpriseCapability if self.is_capability_enabled(cap)]
|
|
115
|
+
|
|
116
|
+
def describe(self) -> Dict[str, object]:
|
|
117
|
+
"""Edition + capability matrix for ``/workspace/editions`` and admin UI."""
|
|
118
|
+
return {
|
|
119
|
+
"edition": self.edition().value,
|
|
120
|
+
"is_enterprise": self.edition() is Edition.ENTERPRISE,
|
|
121
|
+
"capabilities": {
|
|
122
|
+
cap.value: self.is_capability_enabled(cap) for cap in EnterpriseCapability
|
|
123
|
+
},
|
|
124
|
+
"community_notice": (
|
|
125
|
+
"All listed capabilities are Enterprise-only extension points. "
|
|
126
|
+
"The open-source Community edition ships none of them enabled; "
|
|
127
|
+
"see docs/ENTERPRISE.md and docs/EDITION_STRATEGY.md."
|
|
128
|
+
),
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
# Shared singleton seam. Enterprise plugins import this and call
|
|
133
|
+
# ``capability_registry.register_provider(...)`` during their own startup.
|
|
134
|
+
capability_registry = CapabilityRegistry()
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def detect_edition() -> Edition:
|
|
138
|
+
"""Best-effort edition detection.
|
|
139
|
+
|
|
140
|
+
Honours an explicit ``LATTICE_EDITION=enterprise`` opt-in for environments
|
|
141
|
+
that have separately installed an Enterprise provider, but otherwise the
|
|
142
|
+
registry's active provider is the source of truth.
|
|
143
|
+
"""
|
|
144
|
+
env = os.environ.get("LATTICE_EDITION", "").strip().lower()
|
|
145
|
+
if env == Edition.ENTERPRISE.value and capability_registry.edition() is Edition.ENTERPRISE:
|
|
146
|
+
return Edition.ENTERPRISE
|
|
147
|
+
return capability_registry.edition()
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def is_capability_enabled(capability: EnterpriseCapability) -> bool:
|
|
151
|
+
"""Module-level convenience used by Community code at extension points."""
|
|
152
|
+
return capability_registry.is_capability_enabled(capability)
|