Skip to content

Commit ff0758e

Browse files
os-zhuangclaude
andauthored
feat!: upgrade ObjectStack platform 12/13 → 14.7 (spec 14) (#448)
Bump every @objectstack/* package to ^14.7.0 and specVersion to ^14.0.0; app version → 2.1.0. Migrate HotCRM metadata off the ObjectStack 14.0 breaking surface (ADR-0090 vocabulary convergence + enable.* flag gates) and harden seed + opportunity-lifecycle hook for a clean fresh-DB boot. Breaking-change migrations (driven from docs.objectstack.ai/docs/releases/v14): - Approval approvers: type 'role' → 'position' on the opportunity-approval flow (D3 — 'role' now resolves against the org-membership tier, so the sales_manager/sales_director positions routed to nobody and stalled). - FLS keys object-qualified (spec 14.4): sales_rep/service_agent permission sets used bare account.*/opportunity.*/case.* keys that matched nothing; requalified to crm_account.*/crm_opportunity.*/crm_case.* so masking applies. Lint/quality migrations surfaced by spec 14: - fieldGroups referenced by fields on crm_case/contract/product/quote so the grouped record-detail sections actually render. - crm_campaign_member gets a member_number autonumber + explicit nameField (ADR-0079 resolvable record title for the junction object). Fresh-boot fixes: - opportunity-lifecycle hook runs the closed-deal freeze-guard BEFORE the derived-field recompute, so system writes (post-seed ownership backfill) to closed opportunities are no longer rejected — kills 23 boot-time BodyRunner errors. - seed 'completed' task gets completed_date to satisfy completed_date_required. Docs: AGENTS.md now points platform upgrades at the official release notes (docs.objectstack.ai/docs/releases) as the required first reference. Verified: validate + typecheck + build + lint (zero warnings) + test (17/17) green; browser-verified login → dashboards → lists → record detail with live seed data, zero boot errors and no post-login console errors. Claude-Session: https://claude.ai/code/session_01YV2dfQ9eR8NYKLSTVLKavY Co-authored-by: Claude <noreply@anthropic.com>
1 parent d29c214 commit ff0758e

16 files changed

Lines changed: 634 additions & 482 deletions

AGENTS.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,24 @@ Use the most specific `Field` type available from `@objectstack/spec/data`:
167167
> "fail at install" wording is stale. Don't mass-rename UI/automation items to
168168
> chase that warning.
169169
170+
## ⬆️ Platform Upgrades (ObjectStack version bumps)
171+
172+
When upgrading the `@objectstack/*` dependency line, **start from the official
173+
release notes — do not reverse-engineer breaking changes from `node_modules`
174+
changelogs**:
175+
176+
1. **Read the release notes first**: <https://docs.objectstack.ai/docs/releases>
177+
(per-major pages, e.g. `/docs/releases/v14`, carry the breaking-change list
178+
and a migration checklist with before/after examples).
179+
2. Per-package details live in each package's `CHANGELOG.md`
180+
(`node_modules/@objectstack/<pkg>/CHANGELOG.md`) — use these to supplement,
181+
not replace, the release notes. Breaking changes reference ADRs for rationale.
182+
3. Bump all `@objectstack/*` packages **together** (they are version-locked),
183+
update `specVersion` in `objectstack.manifest.json` to the new major,
184+
then run the full verify suite and browser-verify (see below).
185+
4. Record the upgrade in `CHANGELOG.md` following the existing entry format
186+
(what changed on the platform, what metadata was migrated and why).
187+
170188
## 🚫 Out of Scope (Platform Features)
171189

172190
The following are **NOT** in HotCRM's scope — they are platform-level features provided by `@objectstack/runtime` or other platform packages:

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,25 @@
22

33
All notable changes to HotCRM are documented in this file. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); HotCRM follows [Semantic Versioning](https://semver.org/).
44

5+
## [2.1.0] — 2026-07-14
6+
7+
Platform upgrade to ObjectStack **14.7** — a major line bump (from 12/13). Manifest `specVersion` now declares `^14.0.0` (was `^12.0.0`); app version `2.1.0`. ObjectStack 14 completes the ADR-0090 permission-model vocabulary convergence and turns the object `enable.*` capability flags into real runtime gates. This release migrates HotCRM's metadata off every 14.0 breaking surface and hardens the seed + opportunity-lifecycle hook so a fresh-DB boot is completely clean. Built, validated, type-checked, linted (zero warnings), unit-tested (17/17), and browser-verified against `@objectstack/* ^14.7.0` (login → HotCRM app → Executive / Sales / Service / CRM Overview dashboards with live seeded data → Accounts / Opportunities / Cases lists → account record detail with grouped field sections; no boot errors, no post-login console errors).
8+
9+
Upgrade migration was driven from the official release notes at <https://docs.objectstack.ai/docs/releases> (per-major page `/docs/releases/v14`), and [`AGENTS.md`](AGENTS.md) now documents that page as the required first reference for any future platform bump.
10+
11+
### Changed
12+
13+
- **ObjectStack platform → 14.7** across all `@objectstack/*` packages (from `12`/`13`).
14+
- **Approval approvers use `type: 'position'` instead of `type: 'role'` (ADR-0090 D3, spec 14.0).** In 14 the `role` approver type resolves against the better-auth org-membership tier (`sys_member.role`: owner/admin/member) — the CRM's `sales_manager` / `sales_director` are org **positions**, not membership tiers, so under the old spelling the opportunity-approval flow routed to nobody and stalled. Both approval nodes in [`src/flows/opportunity-approval.flow.ts`](src/flows/opportunity-approval.flow.ts) now target the declared positions via `type: 'position'`.
15+
- **FLS keys are object-qualified (spec 14.4, `security-fls-unqualified-key`).** The runtime evaluator matches field-permission keys by `<object>.<field>` prefix; the bare keys in the `sales_rep` and `service_agent` permission sets (`account.*`, `opportunity.*`, `case.*`) matched nothing and their declared masking never enforced. Requalified to `crm_account.*` / `crm_opportunity.*` / `crm_case.*` so the FLS actually applies.
16+
- **`fieldGroups` are now referenced by their fields.** Spec 14's lint flagged `crm_case`, `crm_contract`, `crm_product` and `crm_quote` declaring field groups that no field pointed at — the groups never rendered. Every field on those four objects now carries a `group:` assignment, so record detail pages render the intended grouped sections (verified in the browser on the account/case detail layout).
17+
- **`crm_campaign_member` declares a resolvable record title (ADR-0079).** The junction object had no title-eligible stored field, so records displayed as raw IDs. Added a `member_number` autonumber and pointed `nameField` at it explicitly.
18+
19+
### Fixed
20+
21+
- **Opportunity-lifecycle hook no longer rejects system writes to closed deals.** The `beforeUpdate` freeze-guard ran *after* the derived-field recompute injected `expected_revenue`/`probability` into the input, so the post-seed ownership backfill (and any framework re-stamp) on a closed opportunity was rejected for fields the caller never touched — surfacing as 23 `BodyRunner` errors on every fresh-DB boot. The guard now runs first and judges only the caller's actual field edits; a fresh boot is error-free.
22+
- **Seed task with `status: 'completed'` now sets `completed_date`.** The "Send welcome package to Stark Medical" seed row tripped the `completed_date_required` validation rule (an `Insert operation failed` on every fresh boot). Added `completed_date` to satisfy the rule.
23+
524
## [2.0.0] — 2026-07-07
625

726
Platform upgrade to ObjectStack **12.3** — a major line bump. Manifest `specVersion` now declares `^12.0.0` (was `^10.0.0`); app version `2.0.0`. ObjectStack 12 introduces the **metadata-liveness** gate (ADR-0049): the compiler now emits an advisory warning for any authored property that is parsed but has no runtime consumer. This release migrates HotCRM off that dead surface so `pnpm build` / `pnpm dev` compile with **zero warnings**. Built, validated, type-checked, unit-tested (17/17), and browser-verified against `@objectstack/* ^12.3.0` (login → HotCRM app → Executive / Sales / Service / CRM Overview dashboards with live seeded data and the reworked aggregated tables; no console errors).

objectstack.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export default defineStack({
3131
manifest: {
3232
id: 'app.objectstack.hotcrm',
3333
namespace: 'crm',
34-
version: '2.0.0',
34+
version: '2.1.0',
3535
type: 'app',
3636
name: 'HotCRM',
3737
description: 'AI-Native CRM for the ObjectStack marketplace — Accounts, Contacts, Leads, Opportunities, Cases, Knowledge, Forecasts, Campaigns, Contracts.',

objectstack.manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "https://schemas.objectstack.dev/template-manifest.json",
33
"name": "hotcrm",
4-
"specVersion": "^12.0.0",
4+
"specVersion": "^14.0.0",
55
"manifestId": "app.objectstack.hotcrm",
66
"displayName": "HotCRM",
77
"description": "AI-Native CRM for the ObjectStack marketplace — Accounts, Contacts, Leads, Opportunities, Cases, Knowledge, Forecasts, Campaigns, and Contracts in one production-grade workspace.",

package.json

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "hotcrm",
3-
"version": "2.0.0",
3+
"version": "2.1.0",
44
"description": "HotCRM - Production CRM built on ObjectStack",
55
"private": true,
66
"main": "./objectstack.config.ts",
@@ -26,17 +26,17 @@
2626
},
2727
"packageManager": "pnpm@10.33.0",
2828
"dependencies": {
29-
"@objectstack/account": "^13.0.0",
30-
"@objectstack/cli": "^13.0.0",
31-
"@objectstack/driver-memory": "^13.0.0",
32-
"@objectstack/driver-sql": "^13.0.0",
33-
"@objectstack/driver-sqlite-wasm": "^13.0.0",
34-
"@objectstack/metadata": "^13.0.0",
35-
"@objectstack/objectql": "^13.0.0",
36-
"@objectstack/runtime": "^13.0.0",
37-
"@objectstack/service-analytics": "^13.0.0",
38-
"@objectstack/service-automation": "^13.0.0",
39-
"@objectstack/spec": "^13.0.0"
29+
"@objectstack/account": "^14.7.0",
30+
"@objectstack/cli": "^14.7.0",
31+
"@objectstack/driver-memory": "^14.7.0",
32+
"@objectstack/driver-sql": "^14.7.0",
33+
"@objectstack/driver-sqlite-wasm": "^14.7.0",
34+
"@objectstack/metadata": "^14.7.0",
35+
"@objectstack/objectql": "^14.7.0",
36+
"@objectstack/runtime": "^14.7.0",
37+
"@objectstack/service-analytics": "^14.7.0",
38+
"@objectstack/service-automation": "^14.7.0",
39+
"@objectstack/spec": "^14.7.0"
4040
},
4141
"optionalDependencies": {
4242
"better-sqlite3": "^12.11.1"

0 commit comments

Comments
 (0)