ltcai 1.0.0 → 1.1.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 CHANGED
@@ -36,6 +36,21 @@ Automatic knowledge graph
36
36
  Graph-aware chat, snapshots, memory, agents, workflows, skills, and timeline
37
37
  ```
38
38
 
39
+ ### New in 1.1.0: Organization Workspace Foundation
40
+
41
+ - **Organization Workspace** alongside Personal Workspace — create shared org
42
+ workspaces, list/switch between them, and archive (non-destructively)
43
+ - **Workspace roles & permissions** — `owner`, `admin`, `member`, `viewer`
44
+ mapped to read / write / manage-members / manage-workspace
45
+ - **Workspace-scoped data** — snapshots, memory, agent runs, workflows, traces,
46
+ and timeline carry a `workspace_id`; reads scope via the `X-Workspace-Id` header
47
+ - **CI / release hardening** — Node.js 24 ready workflow, version-scoped
48
+ artifact upload (never `dist/*`), and a release artifact validator
49
+ - **Enterprise extension foundation (open-core)** — a stable seam for a future
50
+ Enterprise plugin; Community ships everything it has today, unrestricted
51
+ (see [docs/ENTERPRISE.md](docs/ENTERPRISE.md) and
52
+ [docs/EDITION_STRATEGY.md](docs/EDITION_STRATEGY.md))
53
+
39
54
  ### New in 1.0.0: AI Workspace OS
40
55
 
41
56
  - Workspace OS command center at `/workspace`
package/docs/CHANGELOG.md CHANGED
@@ -1,5 +1,76 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.1.0] - 2026-05-31
4
+
5
+ > Organization Workspace foundation, open-core Enterprise seam, and CI/release hardening.
6
+
7
+ ### Added
8
+
9
+ - **Organization Workspace foundation** — Workspace OS now distinguishes
10
+ `personal` and `organization` workspace types. A full workspace model
11
+ (`workspace_id`, `name`, `type`, `owner_user_id`, `members`, `roles`,
12
+ `settings`, `created_at`, `updated_at`, `status`) is stored in the existing
13
+ local-first JSON store.
14
+ - **Organization Workspace API** — create org workspace, list workspaces, get
15
+ workspace, update, archive (soft, non-destructive), add/remove member, update
16
+ member role, get workspace summary, activate workspace, and an edition info
17
+ endpoint, exposed under `/workspace/orgs/*`, `/workspace/registry`,
18
+ `/workspace/activate`, and `/workspace/editions`.
19
+ - **Workspace roles and permissions** — `owner`, `admin`, `member`, `viewer`
20
+ mapped to `read` / `write` / `manage_members` / `manage_workspace`. Owners and
21
+ admins manage settings and members; members use the workspace; viewers are
22
+ read-only. Personal workspaces always grant their local user owner rights.
23
+ - **Workspace-scoped data** — Snapshots, Memories, Agent runs, Workflows, answer
24
+ Traces, and Timeline events now carry a `workspace_id`. Reads accept an
25
+ optional `X-Workspace-Id` header / `workspace_id` query to scope results.
26
+ - **Enterprise extension seam (open-core)** — new `latticeai/core/enterprise.py`
27
+ defines an `Edition` enum (`community`/`enterprise`), an
28
+ `EnterpriseCapability` enum, and a runtime `CapabilityRegistry` that a future,
29
+ separately-distributed Enterprise plugin can attach a provider to. The
30
+ Community build ships **zero** enabled Enterprise capabilities and restricts no
31
+ Community feature. Documented in `docs/ENTERPRISE.md` and
32
+ `docs/EDITION_STRATEGY.md`.
33
+ - **Release artifact validator** — `scripts/validate_release_artifacts.py`
34
+ verifies that exactly the expected `whl`/`tar.gz`/`vsix`/`tgz` exist for a
35
+ single version, that internal versions match, that the VSIX contains
36
+ `extension/out/extension.js`, and warns when `dist/` mixes other versions.
37
+ - **Workspace OS UI** — Personal/Organization workspace switcher, current
38
+ workspace indicator, and a minimal organization create / member / role panel
39
+ wired into the existing Workspace OS command center.
40
+
41
+ ### Changed
42
+
43
+ - **CI / release hardening** — `release.yml` opts into Node.js 24
44
+ (`FORCE_JAVASCRIPT_ACTIONS_TO_NODE24`) and bumps `actions/checkout@v5`,
45
+ `actions/setup-node@v5`, `actions/setup-python@v6`. Artifact upload and
46
+ `twine check` are now scoped to the tagged version only — never a `dist/*`
47
+ glob — and the build runs the release artifact validator before upload.
48
+ - Existing 1.0.x Workspace OS state is migrated non-destructively to the v1.1
49
+ workspace model on load; legacy records map to the Personal workspace.
50
+ - Release metadata aligned to `1.1.0` across Python, npm, VS Code extension,
51
+ FastAPI app metadata, and `/health`.
52
+
53
+ ## [1.0.1] - 2026-05-31
54
+
55
+ > CI packaging fix for the VS Code extension build.
56
+
57
+ ### Fixed
58
+
59
+ - **Release (build-only) VSIX packaging** — the `Build VSIX` job failed with
60
+ `Extension entrypoint(s) missing: extension/out/extension.js` because the
61
+ workflow ran `vsce package` without first compiling the TypeScript sources
62
+ (`vscode-extension/out/` is gitignored and absent in a clean CI checkout).
63
+ - Added a `vscode:prepublish` → `compile` (`tsc -p .`) script to
64
+ `vscode-extension/package.json` so `vsce package` always compiles the
65
+ extension entrypoint, aligning the local and CI build paths.
66
+ - Updated `.github/workflows/release.yml` to run `npm run compile` and assert
67
+ `out/extension.js` exists before packaging.
68
+
69
+ ### Changed
70
+
71
+ - Release metadata aligned to `1.0.1` across Python, npm, VS Code extension,
72
+ FastAPI app metadata, and `/health`.
73
+
3
74
  ## [1.0.0] - 2026-05-31
4
75
 
5
76
  > AI Workspace OS integration release.
@@ -0,0 +1,56 @@
1
+ # Lattice AI — Edition Strategy (Open Core)
2
+
3
+ This document records the principles behind the Community / Enterprise split so
4
+ the boundary stays predictable for contributors and users.
5
+
6
+ ## Editions
7
+
8
+ - **Community** — this repository, MIT licensed. Local-first AI Workspace OS:
9
+ local LLMs, knowledge graph, Personal **and** Organization workspaces,
10
+ role-based membership, snapshots, memory, agents, workflows, skills, and the
11
+ auditable timeline. Community is a complete product.
12
+ - **Enterprise** — a separately-distributed plugin adding organization-scale
13
+ governance, identity, compliance, and deployment capabilities. Distributed and
14
+ licensed separately. See [ENTERPRISE.md](ENTERPRISE.md).
15
+
16
+ ## Principles
17
+
18
+ 1. **Community is never crippled.** No existing Community feature is removed,
19
+ throttled, or gated to push Enterprise. The capability seam only answers "is
20
+ this *Enterprise* capability available?" — `False` in the open build — and
21
+ never disables a Community code path.
22
+ 2. **Open-core boundary is a runtime seam, not a fork.** Enterprise attaches via
23
+ `capability_registry.register_provider(...)`
24
+ (`latticeai/core/enterprise.py`). The Community repository contains no
25
+ Enterprise implementation and imports no Enterprise code.
26
+ 3. **Capabilities are declared, not hidden.** `EnterpriseCapability` enumerates
27
+ reserved capabilities so the contract is visible and stable, even though
28
+ Community implements none of them.
29
+ 4. **Local-first stays the default.** Enterprise adds options (tenant isolation,
30
+ air-gapped deployment, SIEM export); it does not move the default experience
31
+ off the user's machine.
32
+ 5. **Graceful by default.** A misbehaving or absent provider must never break a
33
+ Community request; the registry falls back to the Community provider.
34
+
35
+ ## What lives where
36
+
37
+ | Concern | Community (this repo) | Enterprise (separate) |
38
+ |--------|------------------------|------------------------|
39
+ | Personal & Organization workspaces | ✅ | — |
40
+ | Base roles (owner/admin/member/viewer) | ✅ | — |
41
+ | Snapshots / memory / agents / workflows / skills | ✅ | — |
42
+ | Audit timeline (local) | ✅ | — |
43
+ | Capability seam & enum | ✅ (declares) | ✅ (implements) |
44
+ | SSO/SCIM/IdP provisioning | seam only | ✅ |
45
+ | Tenant isolation, compliance retention, eDiscovery | seam only | ✅ |
46
+ | SIEM export, DLP, admin policy packs | seam only | ✅ |
47
+ | Private VPC / air-gapped deployment | seam only | ✅ |
48
+
49
+ ## Detecting edition at runtime
50
+
51
+ - `GET /workspace/editions` → edition + per-capability matrix.
52
+ - `GET /workspace/os` → `edition` block in the Workspace OS summary.
53
+ - `latticeai.core.enterprise.detect_edition()` for in-process checks.
54
+
55
+ In the Community build all of the above report `community` with every Enterprise
56
+ capability `false`.
@@ -0,0 +1,78 @@
1
+ # Lattice AI — Enterprise Edition
2
+
3
+ > **Status:** Foundation / extension seam only. The open-source Community
4
+ > edition in this repository ships **none** of the capabilities below enabled,
5
+ > and contains **no** Enterprise implementation. This document describes the
6
+ > boundary and the roadmap, not shipped code.
7
+
8
+ Lattice AI follows an **open-core** model:
9
+
10
+ - **Community** (this repository, MIT) is fully functional on its own: local
11
+ LLMs, knowledge graph, Personal and Organization workspaces, roles, snapshots,
12
+ memory, agents, workflows, skills, and the auditable timeline.
13
+ - **Enterprise** is a separately-distributed plugin that attaches advanced,
14
+ organization-scale governance and deployment capabilities through a stable
15
+ runtime seam. It is never bundled into the Community build.
16
+
17
+ See [EDITION_STRATEGY.md](EDITION_STRATEGY.md) for the principles that keep this
18
+ boundary honest (Community is never crippled to upsell Enterprise).
19
+
20
+ ## The extension seam
21
+
22
+ The seam lives in [`latticeai/core/enterprise.py`](../latticeai/core/enterprise.py):
23
+
24
+ - `Edition` — `community` (default) or `enterprise`.
25
+ - `EnterpriseCapability` — the enum of reserved capabilities (below).
26
+ - `CapabilityProvider` — the protocol an Enterprise plugin implements.
27
+ - `capability_registry` — a process-wide registry. An Enterprise plugin calls
28
+ `capability_registry.register_provider(...)` at startup. Until then, the
29
+ default `CommunityCapabilityProvider` answers every capability query with
30
+ "Community / disabled".
31
+
32
+ Community code consults the seam at extension points via
33
+ `is_capability_enabled(EnterpriseCapability.X)`. In the Community build this is
34
+ always `False`, so the Community code path is taken and nothing is gated off.
35
+
36
+ The live edition + capability matrix is exposed at `GET /workspace/editions`
37
+ and surfaced in the Workspace OS summary (`GET /workspace/os` → `edition`).
38
+
39
+ ## Enterprise capability roadmap
40
+
41
+ These are declared in `EnterpriseCapability` so the seam is stable and
42
+ discoverable. None are implemented in Community.
43
+
44
+ | Capability | Enum | Summary |
45
+ |-----------|------|---------|
46
+ | Advanced SSO | `SSO_ADVANCED` | Enforced SSO, session policy, SAML/OIDC federation |
47
+ | IdP provisioning | `IDP_PROVISIONING` | Entra ID / Okta user & group provisioning |
48
+ | SCIM | `SCIM` | SCIM 2.0 user/group lifecycle sync |
49
+ | Advanced RBAC/ABAC | `RBAC_ABAC_ADVANCED` | Custom roles, attribute-based policy beyond the 4 base roles |
50
+ | Tenant isolation | `TENANT_ISOLATION` | Hard multi-tenant data isolation |
51
+ | Compliance retention | `COMPLIANCE_RETENTION` | Legal-hold, retention windows, immutable audit |
52
+ | SIEM export | `SIEM_EXPORT` | Streaming audit/event export to Splunk/Sentinel/etc. |
53
+ | Private VPC | `PRIVATE_VPC` | Private-network / customer-VPC deployment controls |
54
+ | Air-gapped deployment | `AIR_GAPPED_DEPLOYMENT` | Fully offline install & update channel |
55
+ | DLP policy | `DLP_POLICY` | Data-loss-prevention scanning & enforcement |
56
+ | eDiscovery | `EDISCOVERY` | Search, hold, and export for legal discovery |
57
+ | Admin policy packs | `ADMIN_POLICY_PACKS` | Centrally-managed org policy bundles |
58
+
59
+ ## How an Enterprise plugin attaches (illustrative)
60
+
61
+ ```python
62
+ from latticeai.core.enterprise import (
63
+ Edition, EnterpriseCapability, capability_registry,
64
+ )
65
+
66
+ class EnterpriseProvider:
67
+ def edition(self) -> Edition:
68
+ return Edition.ENTERPRISE
69
+
70
+ def is_enabled(self, capability: EnterpriseCapability) -> bool:
71
+ return capability in MY_LICENSED_CAPABILITIES
72
+
73
+ # Enterprise package startup:
74
+ capability_registry.register_provider(EnterpriseProvider())
75
+ ```
76
+
77
+ No Enterprise code or credentials live in this repository; the Community build
78
+ imports none of the above.
@@ -1,3 +1,3 @@
1
1
  """Lattice AI - modular server package."""
2
2
 
3
- __version__ = "1.0.0"
3
+ __version__ = "1.1.0"
@@ -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)