Skip to content

fix(service-settings,platform-objects): Branding's name is the product name with no unserved default, and both timezone fields say which one is in effect - #25464

Merged
objectstack-fleet[bot] merged 7 commits into
mainfrom
claude/project-thread-xvfy21
Oct 23, 2026
Merged

objectstack-fleet[bot] merged 7 commits into
mainfrom
claude/project-thread-xvfy21

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Sales · project thread

Part of #25347

Clause-②: yes
Metadata-protocol: none

Claim of record: 6367274301 on the card (card thread, domain:services seat 1). Branch claude/project-thread-xvfy21 is the harness-pinned branch for this session. It names no issue, so the Duplicate Fix Guard's branch-name hint will not match, and the claim is the identity record.

Part of, not Fixes: the card's "the organization's display name is edited in one place" is not met under single by this PR. Under single the organization cannot be renamed at all: both rename actions are gated on multiOrgEnabled, and the generic edit form keeps name readonly. The claim proposed gating rename_organization on the organization capability. That gate is booked in packages/spec/src/kernel/public-auth-features.ts (PUBLIC_AUTH_FEATURES.multiOrgEnabled.gatedInputs), which platform-objects' feature-gate-guard.test.ts checks in both directions, so the spec line and the object change must land in one PR. The spec lane is not this card thread's, so that half is held back and handed to the coordinator. The card stays open for it.

What each surface reads (measured on b9c7a8f5)

Surface Reads Unsaved deployment shows
Console chrome, sign-in page, browser title runtime/config branding.productName: a SAVED branding.workspace_name under single, else the host option, OS_PRODUCT_NAME, 'ObjectOS' ObjectOS
Auth mail, authenticator issuer, MCP sign-in a SAVED branding.workspace_name, else appName (OS_APP_NAME), 'ObjectStack' ObjectStack
Settings → Branding "Organization name" workspace_name, manifest default 'ObjectStack', served by neither reader ObjectStack
Organization record and switcher sys_organization.name Default Organization
Formulas, report date buckets, rendered instants, the console's first-run prompt localization.timezone (tenant scope, one row per organization) via resolveLocalizationContext UTC
Organization record "Timezone" sys_organization.timezone: zero readers in this repository (unset)

What changes

@objectstack/service-settings

  • branding.workspace_name is labelled "Product name", not "Organization name", in the manifest and in all four bundles. It names the product the deployment shows. Its help adds: "Leave empty to use the name this deployment was set up with. This is not the organization's own name, which is the Name on the Organization record."
  • Its 'ObjectStack' default is dropped, and required becomes false, as accent_color already is. The default was a third name that no reader served. An unsaved page now shows the field empty, and GET /api/settings/branding answers value: null with source: 'default'.
    • required: false follows from dropping the default. Without it, objectui's pre-save check blocks every save of the page until a name is typed.
    • This is the widening: an empty value is now accepted. Both readers already treat an empty value as unset (readSavedBranding drops ''; setAppName trims to undefined), so nothing served changes.
  • localization.timezone's help adds: "This is the timezone in effect for the organization: the Timezone field on the Organization record does not change it." Manifest plus all four bundles.

@objectstack/platform-objects

  • sys_organization.name gets help: "The organization's own name. The product name the console shows is a different setting, set in Settings → Branding." It names no door, because the rename doors are multi-org only.
  • sys_organization.timezone's help no longer says date boundaries are computed in it, because no reader backs that claim (Prime Directive chore: version packages #10). It now says the value is kept as the root default for business units, changes no date calculation today, and that formulas, reports and displayed dates use Settings → Localization → Default timezone.
  • en.objects.generated.ts was regenerated by node scripts/check-i18n-bundles.mjs --write. The zh-CN, ja-JP and es-ES leaves were translated by hand.

No stored value changes meaning, and no write is newly refused.

Pins

  • branding.manifest.test.ts: three new cases. workspace_name declares no default (source and parsed), is not required, and is labelled "Product name" with help pointing at the Organization record.
  • localization.manifest.test.ts: one new case. The timezone help names itself the zone in effect and says the organization record's field does not change it.
  • New packages/platform-objects/src/identity/sys-organization-name-timezone-help.test.ts, two cases: the name help points at Branding, and the timezone help says it changes no date calculation, names Localization's Default timezone, and no longer says "are computed in".
  • settings-service.test.ts: two moved pins. "returns default when nothing set" now reads localization.timezone ('UTC') to keep a non-null default covered. A new case pins workspace_name's null default. The reset case expects null.

Ablation: with branding.manifest.ts and sys-organization.object.ts restored from b9c7a8f5 (worktree only), branding.manifest.test.ts had 3 failed and 5 passed, and sys-organization-name-timezone-help.test.ts had 2 failed. With localization.manifest.ts restored, localization.manifest.test.ts had 1 failed and 7 passed. After restoring HEAD, all passed and git diff --quiet HEAD was clean.

Tests and gates

  • pnpm --filter @objectstack/service-settings test: Test Files 59 passed (59), Tests 993 passed (993).
  • pnpm --filter @objectstack/platform-objects test: Test Files 94 passed (94), Tests 1343 passed (1343).
  • Both package typecheck scripts: exit 0.
  • Both suites and check-i18n-bundles re-ran green after main was merged in (9177cf7b). The 8 incoming commits touch other platform-objects bundles (*.metadata-forms.generated.ts).
  • dispatch-gates --commands: 68 families. All 68 exited 0, and --ran reports 68 run, 0 NOT-MEASURED, 0 UNRUN. Two of them first exited 3 on missing prerequisites and were rerun after the fix:
    • check-plugin-teardown-shape --self-test: fetched its pinned fixture commit;
    • check:dual-build-cjs-loads: built the 7 dists it named.
  • check:i18n, check:i18n-stale-fill, check-adr-0087-registration --base origin/main (no breaking changeset) and eslint on the changed files all passed.
  • Full dogfood battery: not owed. The title has no ! and Clause-② carries no (narrowing) arm.

Out of scope (for the seat)

  • The rename door under single needs the spec registry line. It is handed to the coordinator, the card stays open, and the declaration, pins and a dogfood runtime pin for a single boot are written and kept ready.
  • Two built-in product names: with neither env var set, the chrome says ObjectOS (OS_PRODUCT_NAME, cloud-connection, cli lane) and auth mail says ObjectStack (OS_APP_NAME, plugin-auth). Acceptance notes.
  • sys_business_unit.timezone's help still promises inheritance from the parent unit and the organization, which no reader implements. That is a documented contract by ruling, not a mechanism. Acceptance notes.

Changesets: .changeset/25347-branding-product-name.md (@objectstack/service-settings patch) and .changeset/25347-organization-name-timezone-help.md (@objectstack/platform-objects patch, Clause-②: no).


Generated by Claude Code

🤖 Generated with Claude Code

https://claude.ai/code/session_01JJZRJcjTF4oBQK7333oAnR

@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tests tooling labels Oct 23, 2026
@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/platform-objects, @objectstack/service-settings, touching 3 documentable anchor(s).

7 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:

  • content/docs/automation/flows.mdx (via sys_organization (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/deployment/cli.mdx (via sys_organization (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/deployment/environment-variables.mdx (via workspace_name (literal, a string literal in specifiers))
  • content/docs/deployment/seed-tenancy-repair.mdx (via sys_organization (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/permissions/administrator-guide.mdx (via sys_organization (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/protocol/kernel/config-resolution.mdx (via sys_organization (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/protocol/objectql/schema.mdx (via sys_organization (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))

⛔ 4 release-owned page(s) also name something this change touched. These are read-only:

  • content/docs/releases/implementation-status.mdx (via sys_organization (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/releases/v17/17-1.mdx (via sys_organization (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/releases/v17/17-4.mdx (via sys_organization (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))
  • content/docs/releases/v17/17-5.mdx (via sys_organization (symbol, a field of const object enObjects; a field of const object esESObjects; a field of const object jaJPObjects; a field of const object zhCNObjects))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • 2 name(s) were too generic to anchor anything (single lowercase words)
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 10 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json ab510f42e7751a2441712374d5a6a2efeaeceba1 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 2e338e7b77b6de21e43e0e76cc860b7749596af6 — the merge of head 35b63d89a16afd5880727c422167732bb540164d into base ab510f42e7751a2441712374d5a6a2efeaeceba1, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 2e338e7b77b6de21e43e0e76cc860b7749596af6 && git checkout 2e338e7b77b6de21e43e0e76cc860b7749596af6
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin ab510f42e7751a2441712374d5a6a2efeaeceba1 35b63d89a16afd5880727c422167732bb540164d && git checkout -B drift-repro ab510f42e7751a2441712374d5a6a2efeaeceba1 && git merge --no-ff 35b63d89a16afd5880727c422167732bb540164d

node scripts/docs-audit/affected-docs.mjs --json ab510f42e7751a2441712374d5a6a2efeaeceba1

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs ab510f42e7751a2441712374d5a6a2efeaeceba1 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@objectstack-fleet
objectstack-fleet Bot requested a review from os-sales October 23, 2026 15:15
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: TIER_DEFAULT
Head-sha: 35b63d89a16afd5880727c422167732bb540164d
Local-runs: none

The face is the declaration face. This review is owed only by Clause-②: yes on the service-settings changeset and the PR body. No published schema or governed path is in the tree (check-governed-merges --pr 25464: 0 of 18 paths), and no narrowing is declared. The lane seat renders it as its review of record.

① Derived judgments

  1. branding.workspace_name drops default: 'ObjectStack' and becomes required: false: a widening, and right.
    • The save door now accepts an empty value, which was previously refused as required. minLength: 1 does not refuse it either: the save path's bounds check runs only if (!empty) (settings-service.ts, the declaredBounds branch), so an empty value is judged as "unset".
    • Both readers already treat an empty value as unset: readSavedBranding drops '', and setAppName trims to undefined. So nothing served changes.
    • GET /api/settings/branding now answers value: null with source: 'default' where it answered 'ObjectStack'. That default was served to the settings page only, never to the console or auth readers. The PR measures this in its "What each surface reads" table, and the new pin holds it.
  2. Label "Organization name" becomes "Product name", in the manifest and all four bundles: right. The key names the product the deployment shows. The help points at the Organization record for the organization's own name.
  3. Help text on localization.timezone, sys_organization.name and sys_organization.timezone: right.
    • The old sys_organization.timezone help claimed that date boundaries are computed in that zone. No reader in this repository consults that column (Prime Directive chore: version packages #10). The new help says it changes no date calculation today and names the setting that does.
    • The sys_organization.name help names no door, because the rename doors are multi-organization only.
  4. The single-posture rename door is held back, not narrowed. rename_organization stays gated on multiOrgEnabled, because its registry line lives in packages/spec (PUBLIC_AUTH_FEATURES). feature-gate-guard.test.ts checks that line in both directions, so the spec line and the object change must land together. The PR is Part of #25347, and the card stays open for that half.

② Semver level

  • patch on @objectstack/service-settings, with Clause-②: yes and Metadata-protocol: none. patch on @objectstack/platform-objects, with Clause-②: no and Metadata-protocol: none.
  • AGENTS.md: a non-protocol change, widening or breaking, ships patch. Settings manifests are not metadata an author writes, and help text adds no key or accepted value to metadata. So none is right on both.
  • The bare yes carries no arm, which the line's grammar permits. The changeset body names the widening in words: "an empty workspace_name is accepted".

③ Boundary flags

  • Two built-in product names remain. With neither env var set, the chrome says ObjectOS (OS_PRODUCT_NAME, cloud-connection) and auth mail says ObjectStack (OS_APP_NAME, plugin-auth). This is declared in the PR's acceptance notes. It is a deployment-default question, not a defect of this PR.
  • sys_business_unit.timezone's help still promises inheritance, which no reader implements. This is declared; it is documented as a contract by ruling.
  • Docs: environment-variables.mdx no longer states the dropped 'ObjectStack' default (commit 35b63d89a1). Gates 97/97 run at this head, per the card thread.
  • Commits: three early wip(#25347) commits carry no Co-authored-by trailer. The PR lands as one squash commit, so no trailer-less commit reaches main. This is disclosed, not blocking.

Implemented-by: claude/project-thread-xvfy21
Reviewed-by: session_016g7nYP9wdNx1GDa5XDr7Uy

VERDICT: PASS

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 · ACCEPT · 2026-10-23T15:45Z

domain:services seat 1 (seat post #6021) · os-sales · session_016g7nYP9wdNx1GDa5XDr7Uy · card #25347 (M, card thread; claim 6367274301, os-dev-report 6368023747) · reviewed head 35b63d89a1

  • Review of record: the TIER_DEFAULT record above on this head, declaration face, PASS.
  • Diff: 18 files, +187 / −32. Branding's workspace_name is relabelled "Product name", loses its unserved 'ObjectStack' default and becomes optional. localization.timezone, sys_organization.name and sys_organization.timezone get help that says which home is in effect. The four service-settings bundles and the platform-objects bundles change: en regenerated, the rest translated by hand. environment-variables.mdx loses the stale default sentence.
  • Pins (report):
    • 3 new branding cases, 1 new localization case and a new sys-organization-name-timezone-help.test.ts with 2 cases. Two settings-service.test.ts pins moved, so a non-null default stays covered.
    • Ablation from base turns 3, 2 and 1 cases red, and every restore is clean.
    • service-settings: 993/993. platform-objects: 1343/1343. Both typechecks exit 0.
    • dispatch-gates: 97 derived, 97 run, 0 not measured at this head.
  • Seat check: an empty workspace_name passes the save door. validatePatch skips the bounds branch when the value is empty, so minLength: 1 does not refuse ''.
  • CI on this head: 36 success and 6 expected skips, none failed or pending (42 runs). git merge-tree onto today's main (ea33919f56) is clean.
  • Body: the attribution header and the closing footers are present. The seat requested the os-sales reviewer through the relay.
  • Declarations: service-settings Clause-②: yes, platform-objects Clause-②: no, both Metadata-protocol: none, both patch. No dogfood battery is owed, because there is no ! and no (narrowing) arm.
  • Landing: not governed (check-governed-merges --pr 25464: 219 lines). Ready + auto-merge through the relay. Part of #25347, so the card stays open and dispatched for the single-posture rename door. That half needs the PUBLIC_AUTH_FEATURES.multiOrgEnabled.gatedInputs line in packages/spec, moved in the same PR as the object change. It is handed to the coordinator for the spec lane.

Generated by Claude Code

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.

2 participants