Skip to content

service-settings: the default-language option list has a boot window on OS_LOCALIZATION_LOCALE, and its matcher differs from the IdP locale claim's #30456

Closed

Description

@objectstack-fleet

domain:server#4 · os-bill · session_01Utp6CZMkHvuDeVYgTD73qF

Filing gate: ① found by the contract review of PR #30446 (#30286), record 6657571849, should-fixes S2, S3 and S4. Filed by domain:server seat 4. ⛔ Not a claim. Suggested-grade: p3. ⛔ Serial after PR #30446 merges: every item reads code it adds.

What happens

  1. Boot window (S2). app-plugin.ts applies setSupportedLocales and the app bundles in start(), and platform plugins push their bundles at kernel:ready. On a deployment that declares no supportedLocales, a kernel:ready reader (auth-plugin.ts applyLocalizationLocale, seed-locale.ts) can read localization.locale before the list is whole. It gets the declared four, sees OS_LOCALIZATION_LOCALE=vi-VN IGNORED, and records that locale (setDefaultSmsLocale, applyEmailLocale) until the next settings-change event. The override coming into force a tick later fires no event. reportRejectedEnvOverride dedupes on env=value, so its one IGNORED line stands for the boot's lifetime while later reads put the override in force. (AGENTS.md "Startup registry reads".) Not a regression: before PR fix(service-settings)!: Setup's default language offers and accepts the languages the deployment supports, not four hard-coded ones #30446 the value was always refused.
  2. Two matchers (S3). The option table's admits is exact match plus platformLocaleTagOf. idp-locale-claim.ts closes a locale against the same getLocales() with resolveLocale (exact → case → base → variant). So sys_user.locale can hold fr (resolved from fr-FR) while Setup refuses fr-FR where fr is offered, and admits is case-sensitive where resolveLocale is not.
  3. Stale invariant comment (S4). packages/plugins/plugin-auth/src/auth-manager.ts (around L1266–1272) says AUTH_EMAIL_TEMPLATE_LOCALES "are also the four options the localization.locale setting offers, so the two ends agree by construction". After PR fix(service-settings)!: Setup's default language offers and accepts the languages the deployment supports, not four hard-coded ones #30446 they agree through normalizeAuthEmailLocale's pass-through and EmailService's en-US rung, not by construction.

Ask

  1. Close the boot window: re-read at ready time, or have the source answer "not ready" until kernel:ready so the env judgement waits. Pin it with an env override outside the four on a non-declaring deployment.
  2. Name one matcher for "is this locale offered" and use it in both places (reusing resolveLocale is the obvious candidate). Say in the PR whether that widens the accepted set.
  3. Correct the comment.

Activity

  1. added
    bugSomething isn't working
    pm:queueReady for the PM dispatch loop
    domain:serverDomain lane — seat card indexed by label:pm:seat
    on Nov 5, 2026
  2. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: audit · p3 · domain:server · 2026-11-05T13:01Z

    ⛔ Not a claim.


    Generated by Claude Code

  3. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · os-bill · session_01Utp6CZMkHvuDeVYgTD73qF

    Claim: PM loop round 1
    Session: session_01Utp6CZMkHvuDeVYgTD73qF (seat) · dev card thread session_01Utp6CZEhtHfQH5TLEVe3TF
    Account: os-bill
    Branch: claude/project-thread-g5rn8k (the card thread's designated push branch, the recorded platform exception to claude/issue-<n>-<slug>)
    Worktree: objectstack-issue-30456
    Domain: domain:server
    Seat: domain:server#4
    File surface: service-settings localization-locale-options.ts (the option table's matcher), plugin-auth idp-locale-claim.ts / auth-plugin.ts applyLocalizationLocale / seed-locale.ts (the kernel:ready readers and the shared matcher), the stale comment in plugin-auth/src/auth-manager.ts; tests; changesets. ⛔ packages/spec/**, docs/adr/**, .claude/**, repo-root AGENTS.md, ui/**, skills/** (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: default judgment tier (opus) — dispatch-gates --tier: no path-derived mandate, effort: default
    Clause-②: yes (widening, provisional) — item 2 may widen (Setup accepting fr-FR where fr is offered, as the IdP claim already resolves); the dev measures and the PR declares the final value
    Metadata-protocol: none
    Responsibility: a kernel:ready reader can judge OS_LOCALIZATION_LOCALE against a partial locale list; Setup and the IdP claim close a locale with different matchers; a stale invariant comment | none: contract review record 6657571849 S2-S4, source reading | deployments with no declared supportedLocales and an env locale override; users whose IdP sends a regional tag
    Thread-read: 6658671470
    Premise: holds (PR #30446 merged 2026-11-05T15:17Z, bee98366d)
    Serial constraints cleared: seats 2, 3, 5 and 6 answered; seat 2's #30529 / #30447 (auth-plugin.ts, auth-manager.ts) and seat 5's #30548 / #30520 are recorded in the order; second to land merges main.

    Dispatch order: /mnt/project-files/server-seat4/dispatch-30456.md (project shared folder). Ruling section: triage 6658671470 (p3); three items S2, S3, S4 of the PR #30446 contract review. Dispatched on the maintainer's 「任务很多,车道尽量跑满并发」. Fixes #30456.

    Posted 2026-11-05T15:22Z.

  4. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 5, 2026
  5. added 4 commits that reference this issue on Nov 5, 2026
  6. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · os-bill · session_01Utp6CZMkHvuDeVYgTD73qF
    os-dev-report

    Status: done. Draft PR #30589 carries Fixes #30456, head 06b4c86f.

    What it does:

    • Boot window (S2). SettingsServicePlugin holds the option verdict on a sourced key's OS_* override from init until kernel:bootstrapped: while held, an OS_LOCALIZATION_LOCALE the locale list does not admit yet is in force and not reported; at the seal it is judged again, and one still not admitted is reported once (existing reporter, same dedupe) and a localization.locale change is emitted so auth's subscribed reader re-applies. One condition changes in effectiveEnvOverride; the new code is holdOptionSourceVerdicts / sealOptionSources / holdsOptionSourceVerdict. A bare SettingsService judges at once, as before. Pinned on a LiteKernel boot with a kernel:ready reader that runs before the i18n stand-in grows its list: vi-VN (outside the four, gained during kernel:ready) stays in force with no report; xx-XX is held, then reported once and the reader re-reads the default.
    • One matcher (S3). @objectstack/core exports resolveOfferedLocale(requested, offered): resolveLocale's exact/case steps, then the platform table's language, then resolveLocale's base/variant steps (reuse, not a copy). Setup's admits and resolveIdpLocale both call it. Pins: fr-FR where fr is offered, fr where fr-FR is, zh-cn for zh-CN, zh-TW on zh-Hant with both scripts offered, de-DE refused/unset.
    • Stale comment (S4). AUTH_EMAIL_TEMPLATE_LOCALES' docblock (auth-manager.ts) and the same claim in applyLocalizationLocale's comment (auth-plugin.ts) now say the ends agree by normalizeAuthEmailLocale pass-through plus the email service's en-US rung.

    Clause-② measured: yes (widening), as the Claim's provisional value. Nothing accepted before is refused; no needs_decision.

    Deviations: the auth-plugin.ts comment fix goes beyond the card's named file (same stale sentence, comment only; seat 2's #30529/#30447 edit that file, a comment-line conflict at most). An invalid override is in force during kernel:ready, so a one-shot reader at that step (the app's inline seed) can use it before the seal reports it; declared in the PR's acceptance notes. List growth after boot (metadata:reloaded) stays out of scope.

    {
      "issue": 30456,
      "status": "done",
      "branch": "claude/project-thread-g5rn8k",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/30589",
      "head": "06b4c86f",
      "session": "session_01Utp6CZEhtHfQH5TLEVe3TF",
      "premise_still_valid": true,
      "summary": "S2: sourced-key OS_* option verdicts held from SettingsServicePlugin.init until kernel:bootstrapped (sealOptionSources), re-judged there, rejected ones reported once and a change emitted so subscribed readers re-read. S3: core resolveOfferedLocale (resolveLocale exact/case, platform-table language, resolveLocale base/variant) used by Setup's localization.locale admits and plugin-auth resolveIdpLocale. S4: stale AUTH_EMAIL_TEMPLATE_LOCALES comment corrected (and its twin in auth-plugin.ts).",
      "clause_2": "yes (widening)",
      "metadata_protocol": "none",
      "tests": "localization-locale-options.test.ts 18 (4 new: 3 boot-window on a real LiteKernel with a kernel:ready reader before the list grows, 1 matcher through real PUT/GET routes; 1 narrowing pin replaced), idp-locale-claim.test.ts +1, core fallbacks.test.ts +4. Ablation via scripts/ablation-replace.mjs, 6 mutations, each red, each restored, tree clean.",
      "gates": "At 06b4c86f after pnpm install --frozen-lockfile (exit 0) and turbo build 119/119: dispatch-gates --commands derived 67 families, each run with its exit recorded before any pipe, 67 of 67 exit 0; --ran 67 derived, 67 run, 0 NOT-MEASURED, exit 0. pnpm lint exit 0. Package test/typecheck exit 0: core 3017 passed, service-settings 1175 passed, plugin-auth 3985 passed 10 skipped. CI check-runs on #30589: not yet reported.",
      "dogfood_battery": "06b4c86f · os-verify-lock VERDICT command-exit 0 (held 26m17s) · Test Files 420 passed 3 skipped (423) · Tests 3496 passed 36 skipped (3532)",
      "line_budget": "source +146 -29 (8 files), tests +165 -3 (3 files), changeset +14 (1 file); 12 files, 357 changed lines, under the 3000 human-merge threshold",
      "files_changed": ".changeset/30456-default-language-boot-window-one-matcher.md, packages/core/src/fallbacks/{index.ts, memory-i18n.ts, fallbacks.test.ts}, packages/plugins/plugin-auth/src/{auth-manager.ts, auth-plugin.ts, idp-locale-claim.ts, idp-locale-claim.test.ts}, packages/services/service-settings/src/{localization-locale-options.ts, localization-locale-options.test.ts, settings-service-plugin.ts, settings-service.ts}",
      "deviations": "auth-plugin.ts comment corrected beside the named auth-manager.ts one (same stale claim, comment only); invalid override in force during kernel:ready, one-shot readers there may use it before the seal reports it (declared)",
      "collisions": "no service-settings translation key added; auth prelude query-count pin untouched; settings-service.ts setMany env-lock branch untouched; mail/branding manifests and translations untouched",
      "mcp_calls": "0 MCP GitHub calls; GitHub reads through gh api REST (one pull read-back)",
      "api_writes": "2 through the relay: pr_create #30589 (draft, no assignee, no labels, read-back identical) and this comment. Plus git pushes to claude/project-thread-g5rn8k (not REST)",
      "open_questions": [],
      "security_findings": "none",
      "out_of_scope_findings": ["runtime locale list growth after boot (metadata:reloaded) re-judges an override at each read; no held-verdict needed there, noted, not filed"]
    }

    Report taken 2026-11-05T16:58Z.

  7. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · os-bill · session_01Utp6CZMkHvuDeVYgTD73qF

    Landed · PR #30589 · card closed

    Reading Value
    PR #30589 MERGED 2026-11-05T18:05Z, merge commit 1c5cee673; Fixes #30456 closed this card. Seat record 6664967534 on head 06b4c86f (not BREAKING, not governed, Clause-②: yes (widening)).
    main source packages/services/service-settings/src/settings-service-plugin.ts:243 this.service.holdOptionSourceVerdicts(); (sealed at kernel:bootstrapped; one matcher resolveOfferedLocale in packages/core/src/fallbacks/memory-i18n.ts).

    The card's label pm:dispatched and the os-bill assignee come off with this comment.

    Posted 2026-11-05T18:42Z.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdomain:serverDomain lane — seat card indexed by label:pm:seatpriority:p3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions