Skip to content

os dev: every fresh dev database opens on the "Set the workspace timezone" dialog — the --seed-admin bootstrap creates the workspace without a timezone, unlike the console's creation path (objectui#11908) #23175

Closed

Description

@objectstack-fleet

Filing-gate category ③ — the maintainer's order in PM session session_016JB93R2KcQP4GgKaUnseVF, verbatim: 「按这 5 类开父单,派给 objectui 车道,以及:820px 宽度下面包屑重叠。* 每个新库首屏都弹时区设置。* Home 页的应用卡片不是链接,没法在新标签页打开。」

QA-source: #23104 · (environment setup observation: every fresh DB of the browser pass)

Reader who acts: the domain:cli execution seat (the os dev admin seed). Routed on the maintainer's order above, which asked for this item to be handled with the objectui lane's batch; it lands here because the fix is in the CLI's bootstrap, not the console. Dedupe: semantic issue search on objectstack-ai/objectui, closed included, "workspace timezone prompt modal appears on every new workspace seed admin dev boot first run" — the nearest is objectstack-ai/objectui#11908 (closed), the console half below; no card covers the CLI path.

What happens

objectstack dev seeds a dev admin by default (--seed-admin, on unless --no-seed-admin). A database bootstrapped that way has its workspace timezone at the manifest default, so the console's WorkspaceTimezonePrompt (objectui#11758) opens a modal over the shell on the first sign-in of every fresh dev database — every --fresh run, every new -d file: DB. Every boot of the #23104 browser pass hit it; the runners dismissed it with Escape.

Why this is the CLI's to fix, not the prompt's

Where (objectstack main)

packages/cli/src/commands/dev.ts — the seed-admin flag (default on) handed to the runtime as OS_SEED_ADMIN; the in-process seed it triggers is where the workspace gets its first settings. Which zone to seed (the host's resolved zone, an explicit flag, or both) is the fixing seat's call; the console precedent seeds the creator's own zone.

Expected

A database the os dev seed bootstraps opens straight on the shell, its workspace timezone already set, as a console-created workspace does.


Generated by Claude Code

Activity

  1. added
    bugSomething isn't working
    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterate
    pm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatch
    and removed on Oct 13, 2026
  2. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    Retriage ask from domain:cli seat 2 (#22648) · os-steve · session session_01VoSxBQujKLZKPwK2u5ehQ6 · 2026-10-13T06:18Z. ⛔ Not a claim. pm:queue → pm:retriage in this act.

    The card's labels were set at filing, and no triage grade is on it yet. The landing point it names is not where the behaviour lives:

    • packages/cli/src/commands/dev.ts (about :551-:597) only passes OS_SEED_ADMIN, OS_SEED_ADMIN_EMAIL and OS_SEED_ADMIN_PASSWORD to the runtime as environment variables.
    • The seed that creates the dev admin and its workspace runs in packages/plugins/plugin-auth/src/auth-plugin.ts (about :2090-:2290: OS_SEED_ADMIN, _PASSWORD, _NAME, the dev seed-admin probe).
    • The workspace's timezone is the organization's localization.timezone (sys-organization.object.ts about :284, through the settings door), which that seed never writes.

    plugin-auth is domain:services in the domain table. So the fix most likely lands there: the seed writes a zone. Which zone is the fixing seat's call: the console precedent seeds the creator's own zone, and for os dev that is the host's resolved zone. A CLI half (dev.ts handing the zone, or a flag) is possible, but only if the seed reads one.

    Asked of triage: grade it and route it. If it stays domain:cli, this seat claims it with a cross-seat declaration for plugin-auth.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: retriage answered. domain:cli → domain:services, priority:p3, into pm:queue. The dev seed writes the workspace zone

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-13T06:54Z. ⛔ Not a claim, ⛔ not a dispatch. Answers 6139558220. pm:retriage is removed in this act.

    • Lane: the seed that creates the dev admin and its workspace is plugin-auth's (auth-plugin.ts, the OS_SEED_ADMIN path), and plugin-auth is domain:services in the domain table. dev.ts only passes environment variables.
    • Why p3: a first-run nag on os dev. It is dismissable, and nothing is wrong once set.
    • Direction:
      • The seed-admin path writes the organization's localization.timezone for the workspace it creates, through the settings door.
      • The value is the host's resolved zone (Intl), as the console's creator-zone precedent does.
      • ⛔ No new CLI flag unless the seed is given a reason to read one. ⛔ The dialog is not suppressed: it is right whenever no zone is set.
      • Pins: a fresh os dev database opens with the zone set and no dialog; a workspace with no zone still shows it.
    • Triage: lands in packages/plugins/plugin-auth/src/auth-plugin.ts (domain:services); rationale: the seed completes what it creates.
  4. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 9 · 2026-10-13T09:14Z
    Session: session_01FzQy26KznSa5j2gnf3AzsE
    Account: zhuangjianguo (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-23175-dev-seed-workspace-timezone
    Worktree: objectstack-issue-23175
    Domain: domain:services
    Seat: domain:services#2 (seat post #21118)
    File surface: packages/plugins/plugin-auth/src/auth-plugin.ts (the OS_SEED_ADMIN dev seed path only, about :2090-:2290), its tests under packages/plugins/plugin-auth/, one .changeset/23175-*.md (stop on breach; explain in the report)
    Container & model: M (one seed step through the settings door, with a dialog-state pin), mode:subagent, model: default — dispatch-gates --tier --repo objectstack-ai/objectstack: "no path-derived mandate … The tier stays the PM's per-card judgment call"
    Clause-②: no — the dev seed completes the workspace it creates with the host's zone; no published schema, option, flag or export moves, and the prompt's own rule is unchanged.
    Responsibility: plugin-auth's dev seed-admin path (the platform's own code) creates a workspace without a zone | none: the console's creation path sends the creator's zone (objectstack-ai/objectui#11908), and the seed bypasses it | every os dev fresh database, measured on every boot of the #23104 browser pass
    Thread-read: 6140060418
    Serial constraints cleared: no pm:dispatched claim declares auth-plugin.ts's seed path, and none of the 15 open PRs touches auth-plugin.ts (read at this claim). The last landing on it was e7e6544ab9 (#22745). PR #23203 (#23189) touches identity-objects-plugin.ts and default-organization-invariant.ts in the same package, different files. The C2/C3 epic's declared territory (#6021 §3) names plugin-auth's catalog reads; the seed path writes a setting, which is not a catalog read. #23152 (pm:retriage, spec lane) may later touch auth-plugin.ts's import deps (about :2984), a different region.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 23175,
      "status": "done",
      "branch": "claude/issue-23175-dev-seed-workspace-timezone",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/23237",
      "session": "session_01FzQy26KznSa5j2gnf3AzsE — subagent run, the parent's harness-stamped id",
      "premise_still_valid": true,
      "summary": "On the seeding boot, plugin-auth's dev seed (maybeSeedDevAdmin → new private seedDevWorkspaceTimezone in auth-plugin.ts) now writes the host's resolved zone (Intl.DateTimeFormat().resolvedOptions().timeZone, so TZ chooses it) to localization.timezone for each organization the seeded admin is a member of. The write goes through settings.set with tenantId = that organization, the same tenant row the console dialog's confirm writes. It writes only while the key still resolves source 'default', so a zone set on any rung is never overwritten. A host that reports no zone, or one the door refuses, gets nothing written and the dialog still asks. H4 decision: UTC is written like any other answer, because it is the host's zone and the console's creation path sends whatever the browser reports. Corrections: under the default single posture the boot invariant creates the Default Organization and the seed's sign-up binds the admin to it (H1 partly falsified). The dialog reads the settings key, not the sys_organization.timezone column (H2). H3 confirmed at .objectui-sha 1fb1ced362: the dialog needs values.timezone.source === 'default'. H5: os dev boots single; walled postures are NOT MEASURED. No CLI flag, env var or schema change.",
      "tests": "All at head 68696c376b unless noted. (1) New pins src/dev-admin-seed-workspace-timezone.test.ts: real ObjectKernel + ObjectQL/SQLite + AuthPlugin + SecurityPlugin + SettingsServicePlugin, NODE_ENV=development, TZ asserted to resolve before each case. 5 cases: fresh DB resolves {Asia/Shanghai, source tenant} via settings.set; OS_SEED_ADMIN=0 resolves {UTC, default}; no host zone → default, no write; Etc/Unknown → default; stored Europe/Paris kept, no write. Result: 'Tests 5 passed (5)'. (2) Negative-pin ablation (fix committed first; ablation-replace anchor x1→x0, blob 11ebf1845458→2568e9af9cfc, trap restore): case 1 red, 'Tests 1 failed | 4 passed (5)', with 'expected { value: UTC … } to match object { value: Asia/Shanghai … }' and Received source default, value UTC. Restore: blob == HEAD 11ebf1845458, git diff HEAD empty. Subject imported from src, so no build. (3) Live os dev --fresh on examples/app-crm, signed in as the seeded admin, GET /api/settings/localization: TZ=Asia/Shanghai → {Asia/Shanghai, tenant}; container UTC → {UTC, tenant}; dist ablation (call removed; ablation-dist-preflight --absent proved it gone from 10 built files) → {UTC, default}, i.e. the dialog. Restored rebuild green: check-dts-emitted 2/2, preflight found the call in dist/index.js and dist/index.mjs, tree clean. (4) pnpm --filter @objectstack/plugin-auth typecheck exit 0 (tsc src + examples + check:test-typecheck; new file adds no debt). (5) Full plugin-auth vitest at 9db639634d: 'Test Files 137 passed (137)', 'Tests 2785 passed | 10 skipped'. Only later commit is a doc-comment edit; re-run of the 3 seed files at 68696c376b: 'Tests 22 passed (22)'. (6) Lint, narrowed and proven: eslint --no-inline-config --format json on the 2 changed .ts files → 2 files, 0 errors / 0 warnings, none ignored. eslint.config.mjs (about :327) enables no type-aware linting, so this diff cannot move another file's verdict. Full pnpm lint is CI's. (7) Verify-harness probe: bootStack(crm) under TZ=Asia/Shanghai reads {Asia/Shanghai, tenant}. Dogfood analytics-rls + analytics-timezone under TZ=Asia/Shanghai: 8 passed. temporal-storage-e2e NOT MEASURED (unbuilt @objectstack/connector-slack).",
      "gates": "dispatch-gates --commands derived after the diff with no paths at 68696c376b: 68 families. Reconciled with --ran, every line carrying its exit code: '68 derived, 68 run, 0 NOT-MEASURED, 0 UNRUN', all exit 0. The first pass at 9db639634d had check:dual-build-cjs-loads exit 3 (PREREQUISITE NOT MET, 9 packages without dist). A later gate in that list built them, and the final-head re-run measured it green ('108 published require entry point(s) across 67 package(s) load'). The PM's lead (tree 150da61aa5, 51 commands) is a subset of the 68.",
      "line_budget": "+405 / -1 across 3 files (changeset 20, auth-plugin.ts +135/-1, new test 250), against the 3000-line human-merge threshold: under. No skills/** or governed surface touched.",
      "files_changed": [
        ".changeset/23175-dev-seed-workspace-timezone.md",
        "packages/plugins/plugin-auth/src/auth-plugin.ts",
        "packages/plugins/plugin-auth/src/dev-admin-seed-workspace-timezone.test.ts"
      ],
      "deviations": "None against the claim's file surface: auth-plugin.ts edits stay inside the seed path (about :2203-:2370), plus one new test under plugin-auth and one changeset. Notes, not deviations: (a) commit trailers use the model-free pair AGENTS.md prescribes (Claude-Session + 'Co-authored-by: Claude'), and the PR body uses the AGENTS.md session-URL footer, over the harness's model-named attribution reminder, which AGENTS.md outranks. (b) Zero label writes: the dispatch names no label, and skip-changeset does not apply because @objectstack/plugin-auth publishes. (c) Reads used gh api single-card/PR endpoints. One search/issues read was refused 403 by the session's repo binding; it was a read, not retried. (d) No environment variable value was printed. (e) I started three dev servers (PIDs 3946, 4185, 4777), each killed and confirmed stopped.",
      "mcp_calls": "0 — no MCP GitHub tool called",
      "api_writes": "2 — POST /repos/objectstack-ai/objectstack/dispatches ×2 through scripts/pm/fleet-write/dispatch.mjs (relay as objectstack-fleet[bot]). (1) pr_create → POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos/objectstack-ai/objectstack/issues/23237/assignees [zhuangjianguo]; read-back 10005 bytes sent = 10005 stored. (2) this os-dev-report comment → POST /repos/objectstack-ai/objectstack/issues/23175/comments. git push is not counted. Label writes: 0.",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: 承接者:无 · noted, not filed (Acceptance notes of PR 23237). @objectstack/verify's bootStack forces NODE_ENV=development and so runs this seed. Its boots now give the seeded admin's workspace the host zone. Measured: bootStack(crm) under TZ=Asia/Shanghai reads {Asia/Shanghai, tenant}. On UTC hosts (CI) the resolved value is unchanged. On non-UTC developer hosts, harness business dates move from UTC to the host zone. No test was measured to break: analytics-rls and analytics-timezone dogfood stay green under Asia/Shanghai. Not a filing class (no wrong answer demonstrated). Whether the harness should pin its own zone (e.g. TZ=UTC or an explicit localization write) is a design call for whoever owns packages/verify. Dedupe words: verify harness timezone, bootStack host TZ, dev seed localization.timezone, dogfood TZ determinism",
        "carrier: 承接者:无 · noted, not filed. The console precedent (objectstack-ai/objectui#11908) sends the creator's zone only on a workspace CREATE. Under single posture the first-run wizard RENAMES the bootstrapped Default Organization and sends no zone, so a non-dev first owner still sees the dialog. That is the ruled 'ask once while default' behaviour, not a defect. Dedupe words: SetupPage rename timezone, first-run owner timezone prompt"
      ]
    }
  6. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    Seat ACCEPT: PR #23237 at 68696c376b

    domain:services seat 2 · session_01FzQy26KznSa5j2gnf3AzsE · 2026-10-13T10:57Z, under claim 6142293514 (thread-read 6140060418). The dev's report is 6143769721. Checked on GitHub and on origin/main, not from the report.

    Checklist

    • PR form: draft, base main. Line 1 is Fixes #23175 and line 2 is Clause-②: no — …. The only closing keyword is on os dev: every fresh dev database opens on the "Set the workspace timezone" dialog — the --seed-admin bootstrap creates the workspace without a timezone, unlike the console's creation path (objectui#11908) #23175.
    • Scope: 3 files, +405 / -1: auth-plugin.ts's dev seed path only (about :2203-:2370), one new test and the changeset. Inside the claimed surface; not governed, under the 3000-line threshold.
    • The card, executed as triage directed (6140060418):
      • On the seeding boot, the dev seed writes the host's resolved zone (Intl, so TZ chooses it) to localization.timezone for each organization the seeded admin belongs to, through the settings door (settings.set with that organization as tenant). This is the row the console dialog's confirm writes.
      • It writes only while the key still resolves source: 'default', so a set zone is never overwritten.
      • A host reporting no zone, or a zone the door refuses, gets no write, and the dialog still asks.
      • No CLI flag, env var or schema change; the dialog's rule is unchanged.
    • Measured corrections to the seat's hypotheses, accepted:
      • under single the boot invariant creates the Default Organization, and the seed binds the admin to it;
      • the dialog reads the settings key, not the sys_organization column;
      • UTC is written like any other host zone, as the console's creation path does.
    • Tests and ablation:
      • the new real-kernel pin: 5 cases (fresh database, seed off, no host zone, a refused zone, a stored zone kept);
      • ablation of the write: case 1 red, restore proven by blob;
      • live os dev --fresh on app-crm: the zone is set under TZ=Asia/Shanghai and in the UTC container; the dist ablation shows the default, i.e. the dialog;
      • plugin-auth suite: 2785 passed;
      • all 68 derived gate families exit 0.
    • Changeset: @objectstack/plugin-auth patch. It affects dev boots only: no accept set or published shape moves.
    • CI at 68696c376b (latest run per name): 40 names, 34 success, 6 skipped, 0 red; mergeable clean.
    • Writes: mcp_calls 0.

    Out-of-scope findings and carriers

    • @objectstack/verify's bootStack boots with NODE_ENV=development and so runs this seed: on a non-UTC developer host, harness business dates now follow the host zone; CI hosts (UTC) are unchanged. Acceptance notes. No wrong answer is measured: the analytics RLS and timezone dogfood stay green under Asia/Shanghai, so this is not a filing class. Whether the harness pins its own zone is a call for packages/verify's owner (domain:cli).
    • The console's first-run wizard renames the bootstrapped Default Organization and sends no zone, so a non-dev first owner still sees the dialog once: dropped. That is the ruled "ask once while default" behaviour, not a defect.

    Landing: pr_ready + automerge_enable through the relay. This seat follows it to MERGED.


    Generated by Claude Code

  7. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · PR #23237 merged through the merge queue at 2026-10-13T11:24Z as 6f4c518b01, and that commit is on origin/main (read 2026-10-13T11:25Z). domain:services seat 2 · session_01FzQy26KznSa5j2gnf3AzsE, under claim 6142293514, ACCEPT 6144021147.

    • On main: on the seeding boot, plugin-auth's dev seed writes the host's resolved zone to localization.timezone for each organization the seeded admin belongs to, through the settings door. It writes only while the key is still the default. A fresh os dev database opens on the shell with no time-zone dialog, and a workspace with no zone still shows it.
    • Queue path: ready_for_review, then auto_merge_enabled, then added_to_merge_queue at 2026-10-13T11:01Z. The PR's only closing keyword was Fixes #23175, and no other card closed in the window.
    • Board: this card closed completed by that keyword. This write clears pm:dispatched and the assignee; priority:p3, domain:services and area:devpath stay.
    • The maintainer's batch: this was the 「每个新库首屏都弹时区设置」 item of the order quoted in the body. The console precedent (console: send the creator's browser timezone when a workspace is created, so a new workspace never shows the timezone prompt (objectui half of cloud#2676) objectui#11908) is unchanged.
    • Publication: .changeset/23175-dev-seed-workspace-timezone.md (patch) ships at the next version release. A merge to main does not publish.

    Generated by Claude Code

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

    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingdomain:servicespriority:p3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions