Skip to content

feat(settings): localization settings — platform timezone/language/formats (ADR-0053 Phase 2) (#1928)#2006

Merged
os-zhuang merged 1 commit into
mainfrom
feat/localization-settings-p0
Jun 17, 2026
Merged

feat(settings): localization settings — platform timezone/language/formats (ADR-0053 Phase 2) (#1928)#2006
os-zhuang merged 1 commit into
mainfrom
feat/localization-settings-p0

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

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: platform defaultglobaltenantuser) with seven manifests (ai/auth/branding/…). Localization was simply never declared. Declaring it gives, for free:

  • Platform default → global → tenant resolution (your "系统 / 组织" default tiers).
  • A permission-gated settings page (setup.access/setup.write) rendered from the manifest.
  • i18n (en + zh-CN shipped; ja/es fall back to inline labels).

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 收编

resolveExecutionContext now resolves timezone and locale from the localization settings via the settings service (canonical 4-tier cascade), falling back to a direct tenant-scoped sys_setting read, then UTC / en-US. This replaces the hand-rolled sys_user_preference + tenant-only sys_setting path from #1978 (which bypassed the settings abstraction); the per-user tier is dropped per the org-level decision. New ExecutionContext.locale.

Consumer wiring

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_setting fallback, per-user sys_user_preference now ignored, UTC/en-US default, invalid-zone fallback, anonymous → unset.
  • dataset-executor.test.ts — unchanged behavior holds (13 pass).
  • Suites green: service-settings 118, service-analytics 125, runtime 388. DTS builds type-check clean.

Follow-on P0 (separate PRs)

  1. company manifest (legal name, address, tax/VAT, primary contact). 3. security manifest (password policy, session/MFA, IP allowlist, SSO/SCIM) — will honestly mark keys lacking enforcement as planned/experimental.

🤖 Generated with Claude Code

…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>
@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling size/m labels Jun 17, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 3 package(s): @objectstack/runtime, packages/services, @objectstack/spec.

98 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/concepts/architecture.mdx (via @objectstack/spec)
  • content/docs/concepts/cloud-artifact-api.mdx (via packages/runtime, packages/spec)
  • content/docs/concepts/cluster-semantics.mdx (via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx (via packages/spec)
  • content/docs/concepts/implementation-status.mdx (via @objectstack/runtime, @objectstack/spec)
  • content/docs/concepts/index.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx (via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx (via packages/spec)
  • content/docs/concepts/north-star.mdx (via packages/runtime, packages/spec)
  • content/docs/concepts/packages.mdx (via @objectstack/runtime, @objectstack/spec)
  • content/docs/concepts/setup-app.mdx (via @objectstack/spec)
  • content/docs/concepts/skills.mdx (via @objectstack/spec)
  • content/docs/concepts/webhook-delivery.mdx (via @objectstack/spec)
  • content/docs/getting-started/architecture.mdx (via @objectstack/spec)
  • content/docs/getting-started/cli.mdx (via @objectstack/spec)
  • content/docs/getting-started/core-concepts.mdx (via @objectstack/spec)
  • content/docs/getting-started/examples.mdx (via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx (via @objectstack/spec)
  • content/docs/guides/adding-a-metadata-type.mdx (via @objectstack/spec)
  • content/docs/guides/ai-capabilities.mdx (via @objectstack/spec)
  • content/docs/guides/airtable-dashboard-analysis.mdx (via @objectstack/spec)
  • content/docs/guides/analytics-datasets.mdx (via @objectstack/spec)
  • content/docs/guides/api-reference.mdx (via @objectstack/runtime, @objectstack/spec)
  • content/docs/guides/authentication.mdx (via @objectstack/runtime)
  • content/docs/guides/business-logic.mdx (via @objectstack/spec)
  • content/docs/guides/cheatsheets/backward-compatibility.mdx (via @objectstack/spec)
  • content/docs/guides/cheatsheets/error-catalog.mdx (via @objectstack/spec)
  • content/docs/guides/cheatsheets/field-type-gallery.mdx (via @objectstack/spec)
  • content/docs/guides/cheatsheets/field-validation-rules.mdx (via @objectstack/spec)
  • content/docs/guides/cheatsheets/permissions-matrix.mdx (via @objectstack/spec)
  • content/docs/guides/cheatsheets/protocol-diagram.mdx (via packages/spec)
  • content/docs/guides/cheatsheets/query-cheat-sheet.mdx (via @objectstack/spec)
  • content/docs/guides/cheatsheets/quick-reference.mdx (via @objectstack/spec)
  • content/docs/guides/client-sdk.mdx (via @objectstack/spec)
  • content/docs/guides/cloud-deployment.mdx (via @objectstack/runtime)
  • content/docs/guides/common-patterns.mdx (via @objectstack/spec)
  • content/docs/guides/contracts/auth-service.mdx (via packages/spec)
  • content/docs/guides/contracts/cache-service.mdx (via packages/spec)
  • content/docs/guides/contracts/data-engine.mdx (via @objectstack/spec)
  • content/docs/guides/contracts/index.mdx (via @objectstack/spec)
  • content/docs/guides/contracts/metadata-service.mdx (via packages/spec)
  • content/docs/guides/contracts/storage-service.mdx (via packages/spec)
  • content/docs/guides/data-modeling.mdx (via @objectstack/spec)
  • content/docs/guides/deployment-vercel.mdx (via @objectstack/runtime, @objectstack/spec)
  • content/docs/guides/driver-configuration.mdx (via @objectstack/runtime, @objectstack/spec)
  • content/docs/guides/error-handling-client.mdx (via @objectstack/spec)
  • content/docs/guides/error-handling-server.mdx (via @objectstack/spec)
  • content/docs/guides/formula.mdx (via @objectstack/spec)
  • content/docs/guides/hook-bodies.mdx (via @objectstack/runtime, packages/spec)
  • content/docs/guides/kernel-services.mdx (via @objectstack/spec)
  • content/docs/guides/metadata/dashboard.mdx (via @objectstack/spec)
  • content/docs/guides/metadata/field.mdx (via @objectstack/spec)
  • content/docs/guides/metadata/flow.mdx (via @objectstack/spec)
  • content/docs/guides/metadata/index.mdx (via @objectstack/spec)
  • content/docs/guides/metadata/object.mdx (via @objectstack/spec)
  • content/docs/guides/metadata/validation.mdx (via @objectstack/spec)
  • content/docs/guides/metadata/workflow.mdx (via @objectstack/spec)
  • content/docs/guides/packages.mdx (via @objectstack/runtime, packages/services, @objectstack/spec)
  • content/docs/guides/plugin-chatbot-integration.mdx (via @objectstack/runtime)
  • content/docs/guides/plugin-development.mdx (via @objectstack/spec)
  • content/docs/guides/plugins.mdx (via @objectstack/spec)
  • content/docs/guides/production-readiness.mdx (via @objectstack/runtime)
  • content/docs/guides/project-scoping.mdx (via @objectstack/spec)
  • content/docs/guides/public-forms.mdx (via @objectstack/spec)
  • content/docs/guides/runtime-services/audit-service.mdx (via packages/services)
  • content/docs/guides/runtime-services/email-service.mdx (via packages/spec)
  • content/docs/guides/runtime-services/index.mdx (via packages/services, packages/spec)
  • content/docs/guides/runtime-services/queue-service.mdx (via packages/spec)
  • content/docs/guides/runtime-services/settings-service.mdx (via packages/services)
  • content/docs/guides/runtime-services/sharing-service.mdx (via packages/spec)
  • content/docs/guides/runtime-services/storage-service.mdx (via packages/spec)
  • content/docs/guides/security.mdx (via @objectstack/spec)
  • content/docs/guides/seed-data.mdx (via @objectstack/spec)
  • content/docs/guides/single-project-mode.mdx (via @objectstack/runtime)
  • content/docs/guides/skills.mdx (via @objectstack/spec)
  • content/docs/guides/standards.mdx (via @objectstack/spec)
  • content/docs/guides/troubleshooting.mdx (via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/config-resolution.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/http-protocol.mdx (via @objectstack/runtime)
  • content/docs/protocol/objectos/i18n-standard.mdx (via packages/services, @objectstack/spec)
  • content/docs/protocol/objectos/index.mdx (via @objectstack/runtime)
  • content/docs/protocol/objectos/lifecycle.mdx (via @objectstack/runtime, @objectstack/spec)
  • content/docs/protocol/objectos/plugin-spec.mdx (via @objectstack/spec)
  • content/docs/protocol/objectos/runtime-capabilities.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx (via packages/spec)
  • content/docs/protocol/objectql/query-syntax.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx (via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx (via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx (via packages/spec)
  • content/docs/protocol/objectui/record-alert.mdx (via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx (via @objectstack/spec)
  • content/docs/releases/index.mdx (via @objectstack/spec)
  • content/docs/releases/v9.mdx (via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@vercel

vercel Bot commented Jun 17, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jun 17, 2026 5:43am

Request Review

@os-zhuang
os-zhuang merged commit 9afeb2d into main Jun 17, 2026
15 checks passed
@os-zhuang
os-zhuang deleted the feat/localization-settings-p0 branch June 17, 2026 05:48
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant