|
1 | 1 | # ObjectStack Project Master Plan & Status Report |
2 | 2 |
|
3 | | -**Date:** 2026-02-05 |
4 | | -**Version:** 1.0.0 |
| 3 | +**Date:** 2026-02-07 |
| 4 | +**Version:** 1.1.0 |
5 | 5 |
|
6 | 6 | ## 1. Project Master Scheme (项目总体方案) |
7 | 7 |
|
@@ -58,7 +58,14 @@ ObjectStack is designed as a **metadata-driven, post-SaaS operating system**. It |
58 | 58 |
|
59 | 59 | ## 3. Next Development Roadmap (下一步开发计划) |
60 | 60 |
|
61 | | -The immediate focus shifts from **Architecture/Kernel** stability to **Feature/Persistence** implementation. |
| 61 | +The focus shifts from **Architecture/Kernel** stability to **Namespace Isolation** and **Feature/Persistence** implementation. |
| 62 | + |
| 63 | +### Phase 0: Namespace & Ownership Model (Current Week) ← ACTIVE |
| 64 | +**Objective:** Enable multi-vendor object isolation and extension. |
| 65 | +1. **Spec Schemas** ✅: `namespace` in manifest, `ObjectOwnershipEnum`, `ObjectExtensionSchema`. |
| 66 | +2. **Registry Rewrite** 🔄: FQN computation, contributor tracking, priority-based merge. |
| 67 | +3. **Engine Update**: Pass namespace/ownership through registration flow. |
| 68 | +4. **Testing**: Comprehensive ownership scenario tests. |
62 | 69 |
|
63 | 70 | ### Phase 1: Persistence Strategy (Week 1-2) |
64 | 71 | **Objective:** Move beyond in-memory data to persistent storage. |
@@ -94,7 +101,130 @@ The immediate focus shifts from **Architecture/Kernel** stability to **Feature/P |
94 | 101 |
|
95 | 102 | --- |
96 | 103 |
|
97 | | -## 4. Immediate Action Items (Today/Tomorrow) |
| 104 | +## 4. **ACTIVE: Namespace & Object Ownership Model** (当前进行中) |
| 105 | + |
| 106 | +**Date Started:** 2026-02-07 |
| 107 | +**Status:** 🔄 In Progress |
| 108 | +**Branch:** `feature/namespace-ownership` |
| 109 | + |
| 110 | +### 4.1 Problem Statement |
| 111 | + |
| 112 | +Multi-vendor packages from different vendors will inevitably define objects with the same short name (e.g., both `app-todo` and `app-crm` define `task`). The current flat registry causes silent overwrites. Object names are also tied to database table names, requiring a namespace isolation mechanism. |
| 113 | + |
| 114 | +### 4.2 Agreed Solution (Salesforce-style Namespace Model) |
| 115 | + |
| 116 | +#### 4.2.1 Namespace Rules |
| 117 | + |
| 118 | +| Property | Rule | |
| 119 | +|----------|------| |
| 120 | +| **Format** | `^[a-z][a-z0-9_]{1,19}$` (2-20 chars) | |
| 121 | +| **Uniqueness** | Instance-unique (validated at boot) | |
| 122 | +| **Reserved** | `base`, `system` — no FQN prefix applied | |
| 123 | +| **FQN Formula** | `{namespace}__{short_name}` (double underscore) | |
| 124 | +| **Example** | namespace `crm` + object `account` → FQN `crm__account` | |
| 125 | + |
| 126 | +#### 4.2.2 Ownership Model |
| 127 | + |
| 128 | +| Mode | Description | |
| 129 | +|------|-------------| |
| 130 | +| **`own`** | This package is the original author. Only ONE owner per FQN. Defines base schema (table name, primary key, core fields). | |
| 131 | +| **`extend`** | This package adds fields/config to an existing object. Multiple extenders allowed. Fields merged additively. | |
| 132 | + |
| 133 | +#### 4.2.3 Merge Strategy |
| 134 | + |
| 135 | +1. Owner defines the base object. |
| 136 | +2. Extenders sorted by `priority` (lower first, higher wins on conflict). |
| 137 | +3. Fields: additive merge. Same-name field → higher priority wins. |
| 138 | +4. Non-field props (`label`, `description`): last writer by priority wins. |
| 139 | + |
| 140 | +### 4.3 Implementation Checklist |
| 141 | + |
| 142 | +| # | Task | Status | File(s) | |
| 143 | +|---|------|--------|---------| |
| 144 | +| 1 | Add `namespace` to ManifestSchema | ✅ Done | `spec/src/kernel/manifest.zod.ts` | |
| 145 | +| 2 | Add `ObjectOwnershipEnum`, `ObjectExtensionSchema` | ✅ Done | `spec/src/data/object.zod.ts` | |
| 146 | +| 3 | Add `objectExtensions` to StackDefinitionSchema | ✅ Done | `spec/src/stack.zod.ts` | |
| 147 | +| 4 | **Rewrite SchemaRegistry with ownership model** | 🔄 In Progress | `objectql/src/registry.ts` | |
| 148 | +| 5 | Update Engine to pass namespace/ownership | ⬜ Pending | `objectql/src/engine.ts` | |
| 149 | +| 6 | Update Broker shim | ⬜ Pending | `console/src/mocks/createKernel.ts` | |
| 150 | +| 7 | Add `namespace` to example apps | ⬜ Pending | `app-todo/objectstack.config.ts`, `app-crm/objectstack.config.ts` | |
| 151 | +| 8 | Write comprehensive registry tests | ⬜ Pending | `objectql/src/registry.test.ts` | |
| 152 | +| 9 | Update engine tests | ⬜ Pending | `objectql/src/engine.test.ts` | |
| 153 | +| 10 | Build and verify all packages | ⬜ Pending | — | |
| 154 | + |
| 155 | +### 4.4 Key Data Structures (Registry Rewrite) |
| 156 | + |
| 157 | +```typescript |
| 158 | +// Reserved namespaces (no FQN prefix) |
| 159 | +const RESERVED_NAMESPACES = new Set(['base', 'system']); |
| 160 | + |
| 161 | +// Contributor record |
| 162 | +interface ObjectContributor { |
| 163 | + packageId: string; |
| 164 | + namespace: string; |
| 165 | + ownership: 'own' | 'extend'; |
| 166 | + priority: number; // 100 = owner default, 200+ = extender |
| 167 | + definition: ServiceObject; |
| 168 | +} |
| 169 | + |
| 170 | +// Primary storage: FQN → Contributor[] |
| 171 | +objectContributors: Map<string, ObjectContributor[]>; |
| 172 | + |
| 173 | +// Merge cache: FQN → merged ServiceObject |
| 174 | +mergedObjectCache: Map<string, ServiceObject>; |
| 175 | + |
| 176 | +// Namespace uniqueness: namespace → packageId |
| 177 | +namespaceRegistry: Map<string, string>; |
| 178 | +``` |
| 179 | + |
| 180 | +### 4.5 API Changes |
| 181 | + |
| 182 | +```typescript |
| 183 | +// Before |
| 184 | +SchemaRegistry.registerObject(schema, packageId?) |
| 185 | + |
| 186 | +// After |
| 187 | +SchemaRegistry.registerObject(schema, packageId, namespace, ownership, priority) |
| 188 | +SchemaRegistry.resolveObject(fqn) // Returns merged object |
| 189 | +SchemaRegistry.getAllObjects(packageId?) // Returns merged objects |
| 190 | +SchemaRegistry.getObjectContributors(fqn) // Returns all contributors |
| 191 | +``` |
| 192 | +
|
| 193 | +--- |
| 194 | +
|
| 195 | +## 5. Immediate Action Items (Today/Tomorrow) |
| 196 | +
|
| 197 | +1. **Complete Registry Rewrite** — Implement FQN computation, contributor tracking, merge engine. |
| 198 | +2. **Update Engine** — Extract namespace from manifest, handle `objectExtensions` array. |
| 199 | +3. **Test Extensively** — Own/extend/conflict/merge/FQN/uninstall scenarios. |
| 200 | +
|
| 201 | +--- |
| 202 | +
|
| 203 | +## 6. Future Development Roadmap (下一步开发计划) |
98 | 204 |
|
99 | 205 | 1. **Scaffold `packages/plugins/driver-sqlite`**. |
100 | 206 | 2. **Extract Standard Driver Test Suite**: Ensure `packages/core/src/qa` has a reusable test suite that can be applied to new drivers immediately. |
| 207 | +
|
| 208 | +--- |
| 209 | +
|
| 210 | +## Appendix: Design Decision Records |
| 211 | +
|
| 212 | +### DDR-001: Namespace Separator (2026-02-07) |
| 213 | +**Decision:** Use double underscore `__` as FQN separator. |
| 214 | +**Rationale:** |
| 215 | +- Single underscore `_` is common in field names (`created_at`). |
| 216 | +- Dot `.` conflicts with JavaScript property access. |
| 217 | +- Matches Salesforce convention for managed packages. |
| 218 | +
|
| 219 | +### DDR-002: Reserved Namespaces (2026-02-07) |
| 220 | +**Decision:** `base` and `system` namespaces are platform-reserved (no prefix applied). |
| 221 | +**Rationale:** |
| 222 | +- Platform-defined objects like `user`, `organization` should not be prefixed. |
| 223 | +- These objects form the foundation that all apps depend on. |
| 224 | +
|
| 225 | +### DDR-003: Ownership vs Extension (2026-02-07) |
| 226 | +**Decision:** Separate `own` vs `extend` declaration. |
| 227 | +**Rationale:** |
| 228 | +- Clear ownership prevents accidental table creation by extenders. |
| 229 | +- Extension priority enables deterministic merge order. |
| 230 | +- Follows Salesforce pattern of "managed object" vs "managed package extensions". |
0 commit comments