Skip to content

Commit edcad25

Browse files
Copilothotlong
andcommitted
feat: add tenant isolation tests and update ROADMAP.md for Phase N
- 12 vitest-based tenant isolation tests (all passing) - Updated ROADMAP.md to v9.0.0 with Phase N — Enterprise Features - Separated tenant isolation hooks from permission checking hooks - Full test suite: 18/19 suites pass (audit failure is pre-existing) Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
1 parent c81d9fe commit edcad25

File tree

3 files changed

+351
-12
lines changed

3 files changed

+351
-12
lines changed

ROADMAP.md

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# ObjectOS Roadmap
22

3-
> **Version**: 8.0.0
3+
> **Version**: 9.0.0
44
> **Date**: February 12, 2026
5-
> **Status**: Phase MTechnical Debt Resolution ✅ COMPLETE
5+
> **Status**: Phase NEnterprise Features 🔄 In Progress
66
> **Spec SDK**: `@objectstack/spec@2.0.7`
77
> **ObjectUI**: `@object-ui/*@2.0.0`
88
@@ -48,6 +48,7 @@ The integration of **@object-ui** (6 packages at v2.0.0) marks a strategic shift
4848
| Permissions | `@objectos/permissions` ||
4949
| Realtime | `@objectos/realtime` ||
5050
| Storage | `@objectos/storage` ||
51+
| Telemetry | `@objectos/telemetry` ||
5152
| Workflow | `@objectos/workflow` ||
5253

5354
**Server Metrics**: 21,947 source lines · 107 TypeScript files · 47 test files · 350+ tests
@@ -97,7 +98,8 @@ The integration of **@object-ui** (6 packages at v2.0.0) marks a strategic shift
9798
| J | Workflow & Automation UI | Feb 2026 ||
9899
| K | Offline & Sync | Feb 2026 ||
99100
| L | Polish & Performance | Feb 2026 ||
100-
| **M** | **Technical Debt Resolution** | **Feb–Sep 2026** | **🔄 In Progress** |
101+
| **M** | **Technical Debt Resolution** | **Feb–Sep 2026** | **✅ Complete** |
102+
| **N** | **Enterprise Features** | **Feb 2026** | **🔄 In Progress** |
101103

102104
### Phase G Outcomes
103105

@@ -274,6 +276,42 @@ Integrate `@objectos/browser` with the Admin Console for offline-first capabilit
274276

275277
---
276278

279+
## Phase N — Enterprise Features (Current — Feb 2026)
280+
281+
Enterprise-grade capabilities for production multi-tenant deployments and observability.
282+
283+
### N.1 — OpenTelemetry Integration (`@objectos/telemetry`)
284+
285+
New plugin providing OpenTelemetry-compatible distributed tracing.
286+
287+
| # | Task | Priority | Status |
288+
|---|------|:--------:|:------:|
289+
| N.1.1 | TelemetryPlugin with span management and buffered export | 🔴 ||
290+
| N.1.2 | W3C Trace Context propagation (traceparent / tracestate) | 🔴 ||
291+
| N.1.3 | Automatic HTTP request instrumentation (Hono middleware) | 🔴 ||
292+
| N.1.4 | Data operation span creation (CRUD hooks) | 🟡 ||
293+
| N.1.5 | Plugin lifecycle tracing (load/enable hooks) | 🟡 ||
294+
| N.1.6 | OTLP HTTP exporter (Jaeger, Zipkin, Grafana Tempo compatible) | 🔴 ||
295+
| N.1.7 | Console exporter for development | 🟢 ||
296+
| N.1.8 | Probabilistic sampling with configurable rate | 🟡 ||
297+
| N.1.9 | Telemetry stats API (`/api/v1/telemetry/stats`) | 🟢 ||
298+
299+
### N.2 — Multi-tenancy Data Isolation
300+
301+
Extend permissions system with organization-scoped data access control.
302+
303+
| # | Task | Priority | Status |
304+
|---|------|:--------:|:------:|
305+
| N.2.1 | Add `organizationId` to `PermissionContext` | 🔴 ||
306+
| N.2.2 | Add `TenantContext` type for middleware integration | 🔴 ||
307+
| N.2.3 | Automatic tenant field stamping on write operations (create/update) | 🔴 ||
308+
| N.2.4 | Automatic tenant filter on read operations (find/delete) | 🔴 ||
309+
| N.2.5 | Configurable tenant field name (`tenantIsolation`, `tenantField`) | 🟡 ||
310+
| N.2.6 | Metadata fallback for `organizationId` extraction | 🟡 ||
311+
| N.2.7 | 12 tenant isolation tests (write, read, custom field, disabled) | 🟡 ||
312+
313+
---
314+
277315
## Release Timeline
278316

279317
### v1.0.0 — Production Release (Target: March 2026)
@@ -312,8 +350,8 @@ Integrate `@objectos/browser` with the Admin Console for offline-first capabilit
312350

313351
- Phase J.3-J.6: Full Workflow & Automation UI ✅
314352
- Phase K: Offline & Sync ✅
315-
- Multi-tenancy data isolation
316-
- OpenTelemetry integration
353+
- Multi-tenancy data isolation ✅ Phase N.2
354+
- OpenTelemetry integration ✅ Phase N.1
317355

318356
### v2.0.0 — Platform (Target: September 2026)
319357

packages/permissions/src/plugin.ts

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ export class PermissionsPlugin implements Plugin {
9797
// Subscribe to data.* hooks for permission checking
9898
await this.setupEventListeners(context);
9999

100+
// Set up tenant isolation hooks (independent of permission checking)
101+
if (this.config.tenantIsolation) {
102+
await this.setupTenantIsolation(context);
103+
}
104+
100105
context.logger.info('[Permissions Plugin] Initialized successfully');
101106

102107
await context.trigger('plugin.initialized', { pluginId: this.name, timestamp: new Date().toISOString() });
@@ -238,29 +243,45 @@ export class PermissionsPlugin implements Plugin {
238243
// Hook into data operations for permission checking (PRE-Operation)
239244
context.hook('data.beforeCreate', async (data: any) => {
240245
await this.checkDataPermission(data, 'create');
241-
this.applyTenantToWrite(data);
242246
});
243247

244248
context.hook('data.beforeUpdate', async (data: any) => {
245249
await this.checkDataPermission(data, 'update');
246-
this.applyTenantToWrite(data);
247250
});
248251

249252
context.hook('data.beforeDelete', async (data: any) => {
250253
await this.checkDataPermission(data, 'delete');
251-
this.applyTenantFilter(data);
252254
});
253255

254256
context.hook('data.beforeFind', async (data: any) => {
255257
await this.applyRecordLevelSecurity(data);
256-
this.applyTenantFilter(data);
257258
});
258259

259260
this.context?.logger.info('[Permissions Plugin] Event listeners registered');
261+
}
260262

261-
if (this.config.tenantIsolation) {
262-
this.context?.logger.info(`[Permissions Plugin] Tenant isolation enabled (field: ${this.config.tenantField})`);
263-
}
263+
/**
264+
* Set up tenant isolation hooks — separate from permission checking.
265+
* These hooks run independently and enforce organization-scoped data access.
266+
*/
267+
private async setupTenantIsolation(context: PluginContext): Promise<void> {
268+
context.hook('data.beforeCreate', async (data: any) => {
269+
this.applyTenantToWrite(data);
270+
});
271+
272+
context.hook('data.beforeUpdate', async (data: any) => {
273+
this.applyTenantToWrite(data);
274+
});
275+
276+
context.hook('data.beforeDelete', async (data: any) => {
277+
this.applyTenantFilter(data);
278+
});
279+
280+
context.hook('data.beforeFind', async (data: any) => {
281+
this.applyTenantFilter(data);
282+
});
283+
284+
context.logger.info(`[Permissions Plugin] Tenant isolation enabled (field: ${this.config.tenantField})`);
264285
}
265286

266287
/**

0 commit comments

Comments
 (0)