mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-07-20 03:16:14 +00:00
docs(tenancy): record verification evidence
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
# Multi-tenant implementation checklist
|
# Multi-tenant implementation checklist
|
||||||
|
|
||||||
This checklist turns the Workspace architecture into implementation and verification gates.
|
This checklist turns the Workspace architecture into implementation and
|
||||||
|
verification gates. Exact commands and observed results are recorded in the
|
||||||
|
[verification report](./verification-report.md).
|
||||||
|
|
||||||
## Scope guard
|
## Scope guard
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,164 @@
|
|||||||
|
# Multi-tenant verification report
|
||||||
|
|
||||||
|
Date: 2026-07-19
|
||||||
|
|
||||||
|
This report records the implementation and verification evidence for the Core
|
||||||
|
Workspace isolation kernel. It does not claim that the closed SaaS Control
|
||||||
|
Plane or Cloud v2 deployment is production-ready.
|
||||||
|
|
||||||
|
## Repository refs and scope
|
||||||
|
|
||||||
|
- LangBot branch: `feat/multi-tenants`
|
||||||
|
- LangBot implementation commit: `c6f826fe2d2e12cc73479155e8f25566048c1c56`
|
||||||
|
- LangBot base: `origin/master` at
|
||||||
|
`6baeb032a7f76c65337b51c7b58593de4687a61c`
|
||||||
|
- Plugin SDK branch: `feat/multi-tenants`
|
||||||
|
- Plugin SDK commit and LangBot dependency pin:
|
||||||
|
`a1544b6b38a37ba72e3284f2836618144f0742c1`
|
||||||
|
- Space remained on `main` at
|
||||||
|
`5058b039c2629e3b01ebd7358369b50e7df62a1c`, with no tracked changes made by
|
||||||
|
this implementation.
|
||||||
|
|
||||||
|
The SDK protocol is versioned as 0.4.15 but is intentionally consumed from the
|
||||||
|
exact pushed Git commit on this feature branch. Publishing 0.4.15 and replacing
|
||||||
|
the Git pin with a registry pin remain merge-to-master release steps.
|
||||||
|
|
||||||
|
## Automated verification
|
||||||
|
|
||||||
|
### LangBot backend
|
||||||
|
|
||||||
|
```text
|
||||||
|
.venv/bin/ruff check .
|
||||||
|
passed
|
||||||
|
|
||||||
|
changed and untracked Python format check
|
||||||
|
220 files already formatted
|
||||||
|
|
||||||
|
.venv/bin/pytest tests/unit_tests -q
|
||||||
|
2051 passed, 1 skipped, 110 warnings in 26.87s
|
||||||
|
|
||||||
|
.venv/bin/pytest tests/integration -q
|
||||||
|
163 passed, 19 skipped, 28 warnings in 6.00s
|
||||||
|
|
||||||
|
uvx --from uv@latest uv lock --check
|
||||||
|
resolved 277 packages; passed
|
||||||
|
|
||||||
|
git diff --check
|
||||||
|
passed
|
||||||
|
```
|
||||||
|
|
||||||
|
### Database migrations
|
||||||
|
|
||||||
|
- Fresh and upgraded SQLite schemas passed, including verified pre-boundary
|
||||||
|
backups, forced-failure restore, retry, and revision manifest checks.
|
||||||
|
- A disposable PostgreSQL 16 instance exercised fresh and upgraded tenancy
|
||||||
|
migrations: `9 passed, 9 warnings in 8.57s`.
|
||||||
|
- Alembic has one head, `0010_scope_resources`, through the chain
|
||||||
|
`0008_mcp_resource_prefs -> 0009_workspace_tenancy ->
|
||||||
|
0010_scope_resources`.
|
||||||
|
- ORM-to-migration coverage found no missing tenant table.
|
||||||
|
|
||||||
|
### Plugin SDK and runtime
|
||||||
|
|
||||||
|
```text
|
||||||
|
SDK full test suite
|
||||||
|
1029 passed, 18 warnings in 8.20s
|
||||||
|
|
||||||
|
SDK Ruff and action consistency checks
|
||||||
|
passed
|
||||||
|
|
||||||
|
Docker-backed Box integration tests
|
||||||
|
13 passed
|
||||||
|
```
|
||||||
|
|
||||||
|
The SDK remote branch and LangBot Git dependency were both resolved and
|
||||||
|
verified at the same commit recorded above.
|
||||||
|
|
||||||
|
### Frontend
|
||||||
|
|
||||||
|
```text
|
||||||
|
pnpm lint
|
||||||
|
0 errors, 34 warnings
|
||||||
|
|
||||||
|
pnpm build
|
||||||
|
passed; 3167 modules
|
||||||
|
|
||||||
|
pnpm exec playwright test --project=chromium
|
||||||
|
40 passed in 19.9s
|
||||||
|
|
||||||
|
Bot form initialization race pressure test
|
||||||
|
10 passed in 9.4s
|
||||||
|
```
|
||||||
|
|
||||||
|
The browser suite covers singleton bootstrap, explicit multi-Workspace
|
||||||
|
selection under the test policy, selector headers, account-state cleanup,
|
||||||
|
Workspace switching, and invitation terminal-state recovery.
|
||||||
|
|
||||||
|
### Packaging and deployment configuration
|
||||||
|
|
||||||
|
- Docker Compose with Plugin Runtime and Box control tokens passed
|
||||||
|
`docker compose ... --profile all config --quiet`.
|
||||||
|
- Compose, Kubernetes, and the default configuration passed YAML parsing.
|
||||||
|
- Kubernetes selector, volume, and control-token reference checks passed.
|
||||||
|
- `skills/bin/lbs index --check` and `skills/bin/lbs validate` passed.
|
||||||
|
- The staged secret scan found no committed credential; test-token literals
|
||||||
|
were confirmed to be non-secret fixtures.
|
||||||
|
|
||||||
|
## Real browser E2E
|
||||||
|
|
||||||
|
The bundled production web application and backend were started against a
|
||||||
|
clean, temporary SQLite data directory. The following flows were performed in
|
||||||
|
the in-app browser against the real API rather than mocks:
|
||||||
|
|
||||||
|
1. The first Account registered and became owner of the automatically created
|
||||||
|
singleton Workspace.
|
||||||
|
2. The owner created a one-time invitation link.
|
||||||
|
3. A signed-out second Account inspected the fragment-based invitation,
|
||||||
|
registered, accepted it, and entered the Workspace as viewer.
|
||||||
|
4. The same member was cycled through viewer, operator, developer, admin, and
|
||||||
|
owner. Visible controls matched the backend permission matrix, including
|
||||||
|
owner transfer only for an owner.
|
||||||
|
5. A viewer invitation mutation returned 403 `permission_denied`; an owner
|
||||||
|
attempt to create a second OSS Workspace returned 403 `edition_limit`.
|
||||||
|
6. Owner/member account switching, refresh, and a newly opened browser tab
|
||||||
|
recovered only the active Account and singleton Workspace state.
|
||||||
|
7. Used, revoked, expired, and email-mismatched invitation states rendered
|
||||||
|
distinct errors. Terminal tokens were cleared, while the mismatch flow
|
||||||
|
allowed switching to the intended Account.
|
||||||
|
8. With the plugin system disabled, `/api/v1/plugins` and
|
||||||
|
`/api/v1/system/status/plugin-system` both returned 200 after a clean server
|
||||||
|
restart. The only remaining browser console error was the expected failure
|
||||||
|
to reach the optional external Space release feed.
|
||||||
|
|
||||||
|
The test server was stopped, port 15321 was verified free, and the temporary
|
||||||
|
test directory was moved to the system Trash. Multi-Workspace same-name and
|
||||||
|
same-identifier isolation is exercised by the automated test-only Cloud policy;
|
||||||
|
the OSS browser cannot create a second Workspace by design.
|
||||||
|
|
||||||
|
## Final audit
|
||||||
|
|
||||||
|
The final isolation audit found no remaining P0/P1 tenant isolation issue in
|
||||||
|
the OSS singleton-Workspace, multi-user scope. Focused checks also covered the
|
||||||
|
plugin-disabled Workspace fence, invitation fragment/account-switch behavior,
|
||||||
|
and the Bot form initialization sequence. Unrelated untracked workspace files
|
||||||
|
were excluded from both commits.
|
||||||
|
|
||||||
|
## Deliberately incomplete SaaS gates
|
||||||
|
|
||||||
|
Multi-Workspace activation remains unavailable in the open-source bootstrap.
|
||||||
|
Cloud v2 must remain disabled until the following closed-system gates are
|
||||||
|
implemented and independently verified:
|
||||||
|
|
||||||
|
- signed `InstanceManifest` verification and closed `CloudWorkspacePolicy`
|
||||||
|
injection;
|
||||||
|
- authoritative Account, Workspace, Membership, Invitation, placement,
|
||||||
|
entitlement, usage, subscription, and billing services;
|
||||||
|
- generation-aware database transaction and outbox fences through commit;
|
||||||
|
- stable durable object references across placement-generation cutovers;
|
||||||
|
- atomic shared OAuth-state and directory-projection stores;
|
||||||
|
- tenant-safe egress and SSRF enforcement for all configurable outbound URLs;
|
||||||
|
- a greenfield Cloud v2 deployment, without carrying forward the legacy Space
|
||||||
|
deployment model.
|
||||||
|
|
||||||
|
These are release gates, not hidden fallbacks. Mutable Core configuration or an
|
||||||
|
edition flag cannot enable SaaS multi-tenancy.
|
||||||
Reference in New Issue
Block a user