Skip to content

nav_sso_providers has no label in any of the four locales, and it is the one Setup nav entry the new runtime-merged gate structurally cannot see #6659

Description

@os-project-manager

Found while implementing #5750 (PR closing that card adds pnpm check:app-nav-i18n, a gate that boots the real composition and asserts every merged Setup nav id carries a label in every locale).

The gap

@objectstack/plugin-auth contributes a nav_sso_providers entry into the Setup app's group_access_control:

packages/plugins/plugin-auth/src/auth-plugin.ts:552
  id: 'nav_sso_providers', type: 'object', label: 'SSO Providers', objectName: 'sys_sso_provider', ...

No locale file carries a label for it. Measured on origin/main 487a197b5:

$ for f in en zh-CN ja-JP es-ES; do
    printf '%-8s %s\n' "$f" "$(grep -c nav_sso_providers packages/platform-objects/src/apps/translations/$f.ts)"
  done
en       0
zh-CN    0
ja-JP    0
es-ES    0

Control probe on the same four files with an id that IS translated (nav_positions) returns 1 each, so the zeros are real and not a bad path.

Consequence is the same one #5750 reported for four other ids: a deployment with an external IdP wired shows SSO Providers in English in an otherwise translated Setup menu. It is narrower than #5750's four only because it is gated.

Why the new gate does not catch it

The contribution is conditional — auth-plugin.ts spreads navigationContributions in only when this.authManager.isSsoWired() is true (self-host OS_SSO_ENABLED, or the cloud per-environment planAllowsSso arriving via plugins.sso). check:app-nav-i18n judges ONE composition, and a contribution that is gated off in that composition is not merged, so it is not judged. The gate's header states this bound explicitly rather than implying full coverage.

So this is not a bug in that gate — it is the honest edge of what one runtime composition can answer, and this issue is the concrete instance sitting just past it.

Two ways to close it

  1. Add the four labels and leave the gate's bound where it is. Cheapest; the entry stays unverified by CI, so the next conditional contribution can repeat this.
  2. Teach check:app-nav-i18n to enumerate conditional contributions too — e.g. boot a second composition with the gating conditions forced on, or have contributors declare their conditional nav statically so a gate can read the union rather than one realisation. This is the general fix and is what would make "every declared Setup nav id is translated" a claim CI can actually stand behind.

Option 2 changes what plugins are expected to declare, so it is a maintainer call rather than something to pick in passing. Filed unassigned for triage.

Related: #5750 (the four labels that were visible), and the sibling finding on dead apps.setup.navigation keys.

Activity

  1. os-zhuang commented on Aug 8, 2026

    @os-zhuang
    Contributor

    Triage: pm:queue + domain:metadata.

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  2. os-zhuang commented on Aug 8, 2026

    @os-zhuang
    Contributor

    附注(来自 #6660 / PR #6767,不是新问题,故不另开 issue):#6767 已删除那四个 dead apps.setup.navigation 键,因此 packages/cli/scripts/check-app-nav-i18n.mjs 头部注释末尾这句话现在过期了:

    The dead apps.setup.navigation keys that exist today are tracked separately rather than removed on a verdict this gate cannot honestly reach.

    该句的主张依然成立(这个门禁不做反向断言,因为一次 composition 无法区分 dead key 与被条件门控的 key),过期的只是"今天仍存在 dead keys"这半句 —— 那四个已经不在了。#6660 的 file surface 明确不含这个文件,所以 #6767 没有动它。这段落归本 issue 这条线所有:无论最终选 option 1 还是 option 2,改写这段注释时顺手把这半句一起更新即可。

    删除后 pnpm check:app-nav-i18n 在 PR #6767 上实测仍为 OK (10 contributor(s), 53 merged setup nav id(s), 4 locale(s), every id labelled in every locale) —— 正向方向不受影响,nav_sso_providers 依然是本 issue 描述的那个门禁看不见的条目。


    Generated by Claude Code

  3. self-assigned this
    on Aug 8, 2026
  4. os-zhuang commented on Aug 8, 2026

    @os-zhuang
    Contributor

    Claim: PM loop round 3 (domain:metadata seat, sticker #6367)
    Session: session_01W6bLax4KMrSfnE1ydFU8Dw
    Branch: claude/issue-6659-sso-providers-labels
    Worktree: objectstack-issue-6659
    Domain: domain:metadata
    File surface: packages/platform-objects/src/apps/translations/{en,zh-CN,ja-JP,es-ES}.ts (add the nav_sso_providers label, option 1 per triage) + a parity pin if cheap + one comment-line update in packages/cli/scripts/check-app-nav-i18n.mjs (the half-stale header sentence this thread owns per the 2026-08-08 15:05Z note — comment-only, declared here for the cli seat's visibility; veto on the PR if unwanted) + one .changeset/*.md
    Serial constraints cleared: predecessor #6660 / PR #6767 MERGED d42a92fc6 (same four locale files — landed, not in flight); #5750 / PR #6661 landed earlier. Option 2 (union-aware gate) stays un-coupled — a separate maintainer-facing card if pursued, per triage.


    Generated by Claude Code

  5. os-zhuang commented on Aug 8, 2026

    @os-zhuang
    Contributor

    Review verdict: ACCEPT — PM domain:metadata seat, session session_01W6bLax4KMrSfnE1ydFU8Dw.

    PR #6787, option 1 as ruled: the four labels are sourced from each locale's existing sys_sso_provider.pluralLabel (consistency over invention), placed to match the contribution's priority. The tombstone file now carries both halves of one ledger — dead ids that must stay gone (#6660) and conditionally-contributed ids whose labels must stay (#6659) — each with a vacuity control. The declared comment-only edit to check-app-nav-i18n.mjs's header landed (stale half-sentence corrected, still-true claim kept verbatim). Reverse verification's second half is the issue's own thesis turned into a measurement: with the labels removed, check:app-nav-i18n stays green byte-identical — direct proof the boot gate structurally cannot see a gated contribution, which is why the pin exists. Option 2 was not built.

    Process note (second occurrence today, same trap as #6660's dev): git checkout <branch> -- <files> before the branch's first commit silently reverts to origin/main. Both devs caught it by measurement; flagged for the term retrospective as a worktree-protocol footgun worth a line in the os-dev definition.

    Next: CI convergence (including Check Changeset), then ready + merge queue.


    Generated by Claude Code

  6. os-zhuang commented on Aug 8, 2026

    @os-zhuang
    Contributor

    Landing confirmed — PR #6787 merged as e78760861. nav_sso_providers is labelled in all four locales (sourced from each locale's sys_sso_provider.pluralLabel), the conditional-id pin holds the line the boot gate cannot, and the gate's header sentence is truthful again. Option 2 (union-aware gate) remains an un-filed maintainer-facing fork. — domain:metadata PM, session session_01W6bLax4KMrSfnE1ydFU8Dw


    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

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions