feat(settings): localization settings — platform timezone/language/formats (ADR-0053 Phase 2) (#1928)#2006
Merged
Merged
Conversation
…rmats (ADR-0053 Phase 2) Adds a `localization` SettingsManifest — the keystone that makes the Phase 2 reference timezone configurable end-to-end. One manifest gives the full settings stack: platform default → global → tenant cascade + a permission-gated settings page + i18n (en/zh-CN). Keys (organization-level; per-user overrides out of scope for v1): timezone, locale, default_country, date_format, time_format, number_format, first_day_of_week, currency, fiscal_year_start. Benchmarked vs Salesforce/ Workday "Company Information + Locale". - resolver 收编: resolveExecutionContext resolves timezone AND locale from the localization settings via the `settings` service (4-tier cascade), falling back to a direct tenant-scoped sys_setting read, then UTC/en-US. Replaces the hand-rolled sys_user_preference + tenant-only path from #1978 (drops the per-user tier). New ExecutionContext.locale. - analytics wiring: DatasetExecutor threads ExecutionContext.timezone into the query (selection tz → request tz → UTC), so #1982 tz buckets fire for a configured org. Formula today()/datetime already wired (#1979/#1980). - email datetime wiring deferred: only current sendTemplate callers are pre-session auth emails with no org context (SendTemplateInput.timezone exists from #1981 for business-notification callers). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
📓 Docs Drift CheckThis PR changes 3 package(s): 98 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This was referenced Jul 18, 2026
os-zhuang
added a commit
that referenced
this pull request
Jul 18, 2026
Add acceptance tests for the timezone-aware today()/daysFromNow()/daysAgo() functions (compute-tz core of ADR-0053 Phase 2, decision D1). The implementation already shipped (#1998/#2001/#2006); these lock the issue's criteria and pin the DST-boundary + equality behavior: - AC1: today() at 2026-06-16T02:00Z in America/Los_Angeles == UTC-midnight of 2026-06-15. - AC3: reference tz unset vs 'UTC' is byte-for-byte the pre-Phase-2 behavior for all three functions. - AC2: calendar days are correct across both 2026 US DST transitions (spring-forward Mar 8, fall-back Nov 1); a Field.datetime instant compares equal to daysFromNow(n) across DST; a Field.date string matches via the hydration-safe idioms (ordering operators, date(), daysBetween()). - A characterization guard documents the known cel-js equality limitation: a bare `date-string == today()` silently returns false because cel-js's isEqual hard-codes `string == X` to false. This is timezone-independent and cross-cutting; the fix belongs in the data layer (hydrate date fields to Date where field types are known) and is tracked as a separate follow-up. Test-only; no changeset (no functional change). Claude-Session: https://claude.ai/code/session_01SuiM565BZ3TR1VD3prMguB Co-authored-by: Claude <noreply@anthropic.com>
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.
P0 base-settings, item 1 of 3. Part of ADR-0053 Phase 2 (#1928). The keystone that makes the Phase 2 reference-timezone actually configurable end-to-end — previously the resolver read a setting nothing could write.
Why a manifest, not bespoke wiring
ObjectStack already has a settings stack (
@objectstack/service-settings+sys_setting's 4-tier cascade: platformdefault→global→tenant→user) with seven manifests (ai/auth/branding/…). Localization was simply never declared. Declaring it gives, for free:setup.access/setup.write) rendered from the manifest.Keys (organization-level; per-user overrides out of scope for v1)
Benchmarked vs Salesforce/Workday "Company Information + Locale":
timezone(UTC),locale(en-US),default_country,date_format,time_format,number_format,first_day_of_week,currency(USD),fiscal_year_start— grouped Region / Formats / Finance.Resolver 收编
resolveExecutionContextnow resolvestimezoneandlocalefrom thelocalizationsettings via thesettingsservice (canonical 4-tier cascade), falling back to a direct tenant-scopedsys_settingread, thenUTC/en-US. This replaces the hand-rolledsys_user_preference+ tenant-onlysys_settingpath from #1978 (which bypassed the settings abstraction); the per-user tier is dropped per the org-level decision. NewExecutionContext.locale.Consumer wiring
DatasetExecutorthreadsExecutionContext.timezoneinto the query (precedence: explicit selection tz → request tz → UTC), so ADR-0053 Phase 2 · Slice 5: timezone-aware analytics date bucketing #1982's tz-aware buckets now fire for a configured org without callers passing a zone.today()/datetime— already wired (ADR-0053 Phase 2 · Slice 2: thread context into applyFormulaPlan (read-time formula fields) #1979/ADR-0053 Phase 2 · Slice 3: timezone-aware today()/daysFromNow()/daysAgo() #1980).datetime(SendTemplateInput.timezone, ADR-0053 Phase 2 · Slice 4: render datetime in reference timezone (formatters + email) #1981) — intentionally not wired: the only currentsendTemplatecallers are pre-session auth emails with no org context. Capability stays ready for business-notification callers.Tests
localization.manifest.test.ts— schema parse, namespace/scope/version, defaults (UTC/en-US/…), every tz option is a valid IANA zone, key/group structure.resolve-execution-context.test.ts— rewritten localization block: settings-service path (tz+locale), direct-sys_settingfallback, per-usersys_user_preferencenow ignored, UTC/en-US default, invalid-zone fallback, anonymous → unset.dataset-executor.test.ts— unchanged behavior holds (13 pass).Follow-on P0 (separate PRs)
companymanifest (legal name, address, tax/VAT, primary contact). 3.securitymanifest (password policy, session/MFA, IP allowlist, SSO/SCIM) — will honestly mark keys lacking enforcement as planned/experimental.🤖 Generated with Claude Code