Skip to content

chore(deps): upgrade ObjectStack to 17.0.0-rc.2 and migrate the metadata it broke - #663

Merged
xuyushun441-sys merged 2 commits into
mainfrom
claude/objectstack-upgrade-17-0-0-rc2-obn6ci
Aug 3, 2026
Merged

chore(deps): upgrade ObjectStack to 17.0.0-rc.2 and migrate the metadata it broke#663
xuyushun441-sys merged 2 commits into
mainfrom
claude/objectstack-upgrade-17-0-0-rc2-obn6ci

Conversation

@xuyushun441-sys

@xuyushun441-sys xuyushun441-sys commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Description

Bumps every @objectstack/* package from 17.0.0-rc.1 to 17.0.0-rc.2, with specVersion and engines.protocol following.

The version bump alone leaves the app broken. Four of the changes in the rc.1 → rc.2 window are live defects in metadata HotCRM already had — two of them silently disable a whole tier of the product — so this PR migrates them and re-verifies each one against a booted server and a real browser session, not only the unit harness.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Code refactoring
  • Performance improvement
  • CI/CD update

Related Issues

Upstream platform changes migrated here: objectstack-ai/objectstack#4419, #4477, #4414, #4667, #4708, #4336, #4649.

Changes Made

Four live defects, each with the failure it produced:

  • demo_bootstrap could no longer find its user. The sweep opened with get_record(sys_user) on an empty filter, which findOne used to answer with an arbitrary row. rc.2 refuses a findOne that names no record (#4419), so the flow failed on its second node and every seeded record stayed ownerless — "My Leads" / "My Deals" / "My Cases" empty for everyone, and every owner-addressed notify reaching nobody. It now reads a list and binds the first row through an assignment node, which states the arbitrary pick instead of smuggling it through a call that claimed to name one. Branch guarded with has(vars.firstUser) so a zero-user org still completes.
  • lead_conversion could no longer convert a lead. rc.2 holds a screen resume to the screen's declared field contract (#4477), and createOpportunity — a checkbox with defaultValue: false — was marked required. A runner posting only what the user touched had its resume refused outright with INVALID_SCREEN_INPUT. A checkbox has no unanswered state; the flag is gone, and the default (plus the init_defaults assignment) supplies the answer as it always actually did.
  • Nine decision nodes carried an inert copy of their branch predicate, now flagged by flow-inert-node-condition (#4414). The engine reads the out-edges, so the node copy restated the gate without being the gate — and a copy that drifts is a lie about what the flow does. Copies deleted; the totality rationale moved to the edges that decide. Behaviour unchanged.
  • translation.validationMessages removed from all four locale bundles — rc.2 retires the key (#4667), and its three messages matched no rule in this app.

Two pinned "platform gap" assertions flip, because the platform closed the gap — which is exactly what they were written to detect:

  • A filtered measure that selects nothing now reports 0, so a lead source that only ever lost reads 0% instead of blank (#4708).
  • A bare-string condition inside a loop body is now CEL-parsed like its envelope twin (#4336). The explicit envelopes stay: they declare which dialect a predicate is in, and they keep these flows correct on a runtime that still carries the old path.

Validation predicates now fail closed (#4649) — the upstream question test/object-validation-predicates.test.ts filed, answered. An unevaluable predicate used to be skipped silently; it now rejects the write. HotCRM's predicates are already total so nothing changes at runtime, but AGENTS.md and that file now describe the outcome an author actually gets.

Testing

  • Unit tests pass (pnpm test) — 48 files, 1165 passed / 1 skipped
  • Linting passes (pnpm lint) — warnings 10 → 1 (the remaining one pre-dates this PR)
  • Build succeeds (pnpm build), plus pnpm validate, pnpm typecheck, pnpm hygiene
  • Manual testing completed — see below
  • New tests added (if applicable) — existing pins updated to the behaviour they were written to catch

Browser verification (Chromium driving a real Console session against pnpm dev on a freshly seeded + staffed demo org):

Surface Result
Sign-in, app shell, navigation renders
All 9 nav list views rows in every one (Contacts grouped by account, 9 records)
Record detail highlight strip, field groups, Related (15), Attachments
Create an account through the UI persists; account_protection hook normalized the name
4 dashboards charts hydrate (23 / 18 / 30 / 23 Recharts marks); 49 analytics calls, zero failures, real rows
Reports render (81 / 87 / 160 cells)
⌘K global search hits
demo_bootstrap one run claimed 115 records across all 8 objects, both ownership columns
escalate_case declared screen fields ['reason']; resume 200; record escalated / critical / reason / date stamped
#4477 negative resume carrying undeclared recordId400 Unknown screen field, record untouched
lead_conversion untouched checkbox → converts, account + contact created, no opportunity
quote_generation quote created, stage needs_analysisproposal
lead_assignment hot = 1-day SLA, standard = 3-day, unrated = 3-day (edge partition is total)
opportunity_approval $750K → director_signoff pending position:sales_director; $250K → approved outright

Checklist

  • I have added a changeset (.changeset/upgrade-objectstack-17-rc2.md)
  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation (AGENTS.md, CHANGELOG.md)
  • My changes generate no new warnings — author-time warnings drop 14 → 5
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published (@objectstack/* 17.0.0-rc.2 is on npm under the rc dist-tag)

Additional Notes

Correction to an earlier revision of this description. It claimed the e2e Playwright suite fails 11 of 16 as a pre-existing defect. That was wrong, and is retracted: the E2E workflow is green on main and green on this PR. The failures were an artefact of my local run — I pointed the suite at a dev server whose seeds had already been claimed by demo_bootstrap and staffed by demo:staff, so the suite's self-signed-up e2e-admin@hotcrm.test (a plain org member) could read nothing under sharingModel: 'private'. In CI the database is empty and nothing has claimed the seeds, which is why it passes there. The only real content left in that observation is a local-DX footgun: running pnpm test:e2e against a long-lived dev server will start failing once the 10-minute demo_bootstrap schedule fires. Not a blocker and not this PR's to fix.

One genuine pre-existing finding, deliberately not fixed here: billing_address renders as raw JSON on the account detail page instead of a formatted address. Reproduced byte-identically on an origin/main (rc.1) worktree booted side by side, so it is not caused by this upgrade.


Generated by Claude Code

…ata it broke

Bumps every `@objectstack/*` package from 17.0.0-rc.1 to 17.0.0-rc.2, with
`specVersion` and `engines.protocol` following. Four of the changes in that
window were live defects in metadata this app already had:

- `demo_bootstrap` opened with `get_record(sys_user)` on an empty filter.
  17.0.0-rc.2 refuses a `findOne` that names no record (#4419), so the sweep
  failed on its second node and every seeded record stayed ownerless — the
  "My …" views empty for everyone and every owner-addressed notify reaching
  nobody. It now reads a list and binds the first row through an `assignment`
  node, stating the arbitrary pick instead of smuggling it through a call that
  claimed to name one, and guards the branch with `has(vars.firstUser)`.

- `lead_conversion` marked `createOpportunity` — a checkbox with
  `defaultValue: false` — as `required`. rc.2 holds a screen resume to its
  declared field contract (#4477), so a runner posting only what the user
  touched had the resume refused with INVALID_SCREEN_INPUT and the lead could
  not convert. A checkbox has no unanswered state; the flag is gone.

- Nine `decision` nodes carried an inert copy of their branch predicate, now
  flagged by `flow-inert-node-condition` (#4414). The engine reads the
  out-edges, so the copy restated the gate without being the gate. Deleted,
  with the totality rationale moved to the edges that decide.

- `translation.validationMessages` is retired (#4667); its three messages
  matched no rule here and had never been read.

Two pinned platform-gap assertions flip because the platform closed the gap —
a filtered measure selecting nothing now reports 0, so a lead source that only
ever lost reads 0% rather than blank (#4708), and a bare-string condition
inside a loop body is CEL-parsed like its envelope twin (#4336). The explicit
envelopes stay. Validation predicates now fail closed (#4649), which does not
change HotCRM's already-total predicates but does change what an author gets,
so AGENTS.md and the predicate test say so.

Verified on a booted server and in a real browser session: navigation, all
nine list views, record detail, UI create, four dashboards (49 analytics
calls, zero failures), reports, global search, and each touched flow —
escalate_case, lead_conversion, quote_generation, lead_assignment, and the
two-tier opportunity_approval routing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UEVSbh8TdK8NRdF7mxVB1a
@vercel

vercel Bot commented Aug 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
hotcrm Ignored Ignored Aug 3, 2026 3:47pm

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation ci/cd CI plumbing and the verification pipeline dependencies Dependency bumps and lockfile changes metadata Declarative metadata — schema, security posture, UI surfaces backend Server-side behaviour — hooks, flows, actions labels Aug 3, 2026
`check-stackblitz-lock.mjs` failed on the upgrade commit: the version bump
touched `package.json` and `pnpm-lock.yaml` but left `package-lock.json` on
the rc.1 line, so the StackBlitz demo would fall back to a full re-resolve
instead of installing from the lock. Regenerated with the command the gate
prints; it now carries rc.2 for all twelve `@objectstack/*` packages and no
rc.1 references remain.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UEVSbh8TdK8NRdF7mxVB1a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend Server-side behaviour — hooks, flows, actions ci/cd CI plumbing and the verification pipeline dependencies Dependency bumps and lockfile changes documentation Improvements or additions to documentation metadata Declarative metadata — schema, security posture, UI surfaces

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants