Repository navigation
fix(service): retire crm_case.created_date — cases use the platform's created_at - #2009
Merged
Merged
Conversation
… platform's created_at The case object declared a readonly created_date beside the created_at the platform injects and stamps on every insert. Nothing wrote it on a real case (only the seeds set it), so a case created through the UI or REST stored null and fell out of Cases Opened by Priority x Day and the service dashboard's date range. Retired following the #575 B2 precedent on crm_opportunity: the report, the case_metrics dataset dimension, the dashboard range and the daily volume widget, the case_timeline view, the case_sla_defaults resolution-time chain and the seeds now read or author created_at. The seeds keep their history because @objectstack/objectql 17.7.0 keeps a seed row's authored created_at on first insert (objectstack#21646). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zh91QzFgePbkmuHnugLN3
…nd move the case tests to created_at New test/case-creation-date.test.ts: crm_case declares no created_date, no locale pack labels it, and every case surface reads created_at; executed on a real kernel (sqlite-wasm), a case inserted with no date is stamped by the platform and counted by Cases Opened by Priority x Day and inside the service dashboard range, and a seed-context row keeps its authored created_at. The existing case/dashboard tests move their fixtures and predicates from created_date to created_at, and read a range field's type off the platform-materialised object (applySystemFields). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zh91QzFgePbkmuHnugLN3
…geset for the created_at move cases.mdx in all three locales: crm_case declares 24 fields, the SLA & Priority group loses Created Date, resolution time is measured from the case's creation moment (the platform's own timestamp), and the Details-tab arithmetic follows the field count. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zh91QzFgePbkmuHnugLN3
….created_date is retired Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zh91QzFgePbkmuHnugLN3
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
This was referenced Oct 8, 2026
This was referenced Oct 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1992
Clause-②: no
This PR retires
crm_case.created_date. Every reader moves to the platform-injectedcreated_at, following ruling5974449549(option A, the maintainer's 「决裁的三张同意」), which was restarted by6037965448(「1992 重启」). It is the same change #575 B2 made oncrm_opportunity. Before this PR, a case created in the UI or through REST storedcreated_date: null, so "Cases Opened by Priority × Day" and the service dashboard's date range left it out.Step one: fresh-boot probe on 17.7.0, measured before any edit
The probe ran on this branch's tree at
c9678036, which isorigin/mainwith@objectstack/*17.7.0. The installed@objectstack/objectqlCHANGELOG.md:424readsbe55fd2: A seed row's authored created_at is kept when the row is first inserted … (#21646).Method:
pnpm build(underos-verify-lock,VERDICT command-exit 0) and copieddist/objectstack.jsoninto the scratchpad.crm_caseseed rows in the copy only. "Data export timing out for large datasets" gotcreated_at: { dialect: cel, source: daysAgo(5) }. "How to configure SSO with Okta?" gotcreated_at: '2026-09-01T12:00:00.000Z'.objectstack start -p 4820 --artifact COPY --home FRESH_HOME -d file:FRESH_HOME/db.sqlitefrom a directory with noobjectstack.config.ts. The banner read "No objectstack.config.ts found — booting from artifact", and the database file did not exist before the boot.GET /api/v1/data/crm_case, which returned 38 rows.created_atdaysAgo(5)2026-10-03T00:00:00.000Z2026-09-01T12:00:00.000Z2026-09-01T12:00:00.000Zcreated_at)2026-10-08T02:31:17.592Z, the seed-time instantBoth authored instants were kept on the first insert, and the control row got the boot instant. Mechanism assumption 1 holds, so the retirement went ahead. Had the probe failed, the card would have stopped here.
What changed
case.object.ts:created_dateis removed, and a comment in the Follow-up to #514: remaining behaviour fixes, conventions, and the action-sandbox test gap #575 B2 shape says why. Theslafield group drops from 7 members to 6. The object has 24 fields; it had 25.case.report.ts: "Cases Opened by Priority × Day" buckets oncreated_at. ItsruntimeFilter: { created_date: { $ne: null } }is gone. That filter only ever excluded the cases nothing had stamped, and every case now carriescreated_at. The false comment saying "created_dateis stamped by the platform" is replaced.case.dataset.ts: thecase_metricsday dimension is nowcreated_at(label "Created",dateGranularity: 'day'). It has the same name and field thataccount_metricsandlead_metricsalready use.service.dashboard.ts:dateRange.field, plus thedaily_case_volumefilter and dimension, usecreated_at.case.view.ts:case_timeline.startDateFieldiscreated_at, the same spellingdeal_timelineuses. The create-form roster comment is updated to match.case.hook.ts: the resolution-time chain readsinput.created_at, thenprevious.created_at.created_atis stamped bysys_stamp_audit_insertat priority 10, beforecase_sla_defaultsat priority 200; objectql sorts hooks ascending.service.seed.ts: the 8 literal case rows and the 30-row generator authorcreated_at. ThecelCaseSlaDuedoc now readscreated_at + matrix.src/sales/data/_shared.ts(seed doctrine rule 1) andsrc/sales/data/sales.seed.ts.crm_case.created_datelabel is removed from all 4objects.service.tspacks. In thecase_metricsblocks of the zh-CN, es-ES and ja-JPapp.tsfiles, the dimension keycreated_dateis nowcreated_at, with the labels unchanged.content/docs/service/cases{,.zh-Hans,.zh-Hant}.mdx. The SLA & Priority row no longer lists Created Date. Resolution time is measured from the case's creation moment. The field count goes 25 to 24, and the Details-tab arithmetic follows (fifteen to fourteen, eight to seven).docs/STATUS.md: thepnpm validatetranscript reads 358 fields; it read 359. This file is outside the claim's file surface. The edit is forced bytest/docs-declared-versions.test.ts, which went red on the firstpnpm verify..changeset/1992-case-created-at.md(patch, the same bump as Follow-up to #514: remaining behaviour fixes, conventions, and the action-sandbox test gap #575 B2). It is written for the release-notes reader, with a FROM → TO section.Reader roster, re-taken by hand on
c9678036I ran
git grep -c created_dateand classified each hit:created_at: everything listed above, plus 8 test files.crm_opportunity:src/sales/objects/opportunity.object.ts,src/sales/views/opportunity.view.ts, and the opportunity half oftest/opportunity-creation-date.test.ts.CHANGELOG.mdhits.content/docshas zerocreated_datehits, as the earlier dev found. The case pages do name the field by its label (Created Date / 创建日期 / 建立日期) in all three locales. Those mentions are covered under Docs above.Tests
test/case-creation-date.test.tshas eight tests:crm_casedeclares nocreated_date; no locale pack labels it; the report column, the dashboard range andcase_timelinereadcreated_at; nothing overcase_metrics, its reports, the service dashboard or the case views namescreated_date.ObjectQLPlugin, so the platform's own audit hook does the stamping), a case inserted with no date at all is stamped and counted by the shipped report, using its rows, columns, values and runtimeFilter. It lands on today's bucket and inside the dashboard'slast_7_dayswindow. A row written inSEED_WRITE_EXECUTION_CONTEXTkeeps its authoredcreated_atand lands on its authored day.created_at:dashboard-date-range-window,dashboard-agent-global-filter,dataset-granularity,docs-service-index-analytics,seed-consistencyandcase-create-form-narrowing. The last one loses itscreated_dateroster entry; "ten above" becomes "nine above".opportunity-creation-date: the test "crm_case keeps its own created_date" is removed, because it now asserts something false. The header comment points to the new file.action-referencesanddashboard-date-range-windownow read a range field's type from the platform-materialised object (applySystemFields).created_atis injected and never listed infields. Without this, the dashboard would drop out ofdatetimeWindowedand leave the window tests with nothing to run.Reverse verification. The fix was committed first (HEAD
9440aec). The 16srcpaths off7b9192were set back toc9678036withgit checkout, and the committed new test was run against them. I predicted red. It ranTests 6 failed | 2 passed (8), exit 1. The 4 static tests failed, and both executed tests failed: "the report dropped a case: []: expected +0 to be 2" and "the last-7-days range left a case out: expected +0 to be 2". The two that stayed green are the non-vacuity check and the platform-stamp positive control. Restore:git checkout HEAD -- PATHS, thengit diff HEADwas empty and all 16 blob hashes matched HEAD. The script carried atrapon EXIT/INT/TERM.Fresh boot after the change (mechanism assumption 3)
I booted the branch's own
dist/objectstack.json(built from0e354fa, unedited) the same way on a fresh database. Then I signed up and made one REST create:POST /api/v1/data/crm_case, status 201, CASE-00039,created_at 2026-10-08T02:47:06.056Z.GET /api/v1/data/crm_casereturned 39 rows. Theircreated_atvalues span 31 distinct UTC days, 2026-09-08 to 2026-10-08. The only row on 2026-10-08 is the REST-created case. The three rows from step one readdaysAgo(2)= 2026-10-06,daysAgo(3)= 2026-10-05 anddaysAgo(5)= 2026-10-03.POST /api/v1/analytics/dataset/querywithcase_metrics,dimensions [priority, created_at]andcase_countreturned 39 cells totalling 39. The REST case appears as{ priority: High, created_at: 2026-10-08, case_count: 1 }.created_at:last_90_dayscounted 39 andlast_7_dayscounted 15.Coupling with #2003
The case
slagroup now has 6 members: priority, closed_date, first_response_date, resolution_time_hours, sla_due_date, is_sla_violated. Thecase_detail.page.tsnote #2003 added ("Not onsla: outside the strip its members are stamps no one types (closed_dateandresolution_time_hoursat close,first_response_datebyevent.hook.ts)") already names exactly the three non-strip members of the 6-member shape, so it still reads right. #2003's changeset sentence ("SLA & Priority, whose dates are recorded for you") also still holds.Acceptance notes
defineSeed(Case, …)does not type-check record keys. In a trap-restored mutation, a seed keycreated_atxoncrm_casepassedtsc --noEmit(exit 0) andpnpm validate("Validation passed", exit 0). The@objectstack/specdefineSeeddoc promises "typos in record field names are caught at compile time". This is a platform-side finding, reported to the seat for upstream filing. What the runtime does with such a key is not measured.content/docs/service/cases*.mdxstill describes three authored sections ("Case Information / Status & SLA / Description", 10 fields).case_detail.page.tshas declared six{ group }sections since crm_case 与 crm_lead 同病:三套互不相同的字段分组(fieldGroups 6 / 详情页 3 / 表单 3),escalated_date 三处写入、零处展示 #970. This PR only corrected the field counts and removed the retired field's mentions.Gates
pnpm verifyonc05b442(git rev-parse --short HEADprinted by the same run), underos-verify-lock:VERDICT command-exit 0.sales_home_pagepage:cardone, also present on base.i18n/missing-*issues"describe.runIf(!bucketsAreHonoured)16.x branch indataset-granularity.pnpm verifyon0e354fawas red in exactly one test,docs-declared-versions("Fields: page says 359, the stack registers 358").c05b442updates the transcript.Generated by Claude Code