Skip to content

Console: an "App lock" entry on the profile page when the mobile shell exposes openAppLockSettings() #29748

Closed

Description

@objectstack-fleet

repo:mobile#1 · os-justin · session_01QSeKYnW1Xf6HDSWz1eGAqv

Filing category ③: a direct task from a maintainer ruling. The ruling is objectstack-ai/mobile#145 comment 6593856498: Ruling: batch #1 item 2 · letter A · maintainer 「同意」. Under option A, the lock is changed only on the shell's native settings screen. The Console reads it and opens that screen; it never writes the lock.

What the shell offers

The shell side is objectstack-ai/mobile#181; the contract is in mobile docs/HYBRID-SHELL.md, section "App lock".

  • getAppLock() resolves { enabled: boolean, timeoutSeconds: number }.
  • openAppLockSettings() opens the native settings screen. Changing the setting there asks for biometrics.
  • Feature-detect each with has('getAppLock') and has('openAppLockSettings'). Only pages on the configured server's origin may call them.
  • No event announces a change. Re-read getAppLock() when the profile page is shown.

Ask (Console, ui/)

  • On the user profile / personal settings page, when has('openAppLockSettings'), show an "App lock" row with its current state from getAppLock(). Tapping it calls openAppLockSettings().
  • In a plain browser or an older shell, show nothing.
  • ⛔ No Console-side toggle. The ruling keeps all writes native.

Business reason

  • Who benefits: phone users who expect the lock under their profile settings, where other apps put it.
  • If not done: the lock stays reachable only from the shell's connection switcher.

Who acts

The domain:ui seat. Triage decides the grade.

Duplicate check (2026-11-03)

is:issue openAppLockSettings in this repo returns 0 hits.

Activity

  1. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: first-touch audit · p3 · domain:ui · pm:queue · 2026-11-03T03:58Z

    ⛔ Not a claim.

    • Read fresh. An "App lock" row on the profile page when the shell exposes openAppLockSettings(). The Console reads the lock and never writes it. Maintainer-ruled A (mobile#145). The lock itself already works in the shell, so this is discoverability: p3.

    Generated by Claude Code

  2. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu

    Claim: PM loop round 19 · 2026-11-03T04:16Z
    Session: session_01QsR2jSM2R4osc3dyaqPHY1 (card thread, os-dev); dispatched by seat session session_01QsR2jUJ19MstFvFhjgiYTu
    Account: zhuangjianguo
    Branch: claude/project-thread-y37yg8 (platform-assigned to the card thread; it can push only this branch)
    Worktree: objectstack-issue-29748
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: ui/packages/mobile/src/nativeHost.ts (two capability union members, optional getAppLock? / openAppLockSettings? on the host interface, a NativeAppLock type, nativeGetAppLock, nativeOpenAppLockSettings), ui/packages/mobile/src/index.ts (their exports), ui/packages/mobile/src/__tests__/nativeHost.test.tsx, ui/packages/mobile/README.md, ui/apps/console/src/pages/system/ProfilePage.tsx (an App lock card only when nativeHostCan(host, 'openAppLockSettings'): read on mount, on visibilitychange to visible and on window focus; tap calls nativeOpenAppLockSettings; no toggle), new ui/apps/console/src/pages/system/__tests__/ProfilePage.appLock-29748.test.tsx, the keys profile.appLock.{title,off,onImmediately,onAfter} in all ten packs under ui/packages/i18n/src/locales/, and a root .changeset (patch). Any other file is declared by a claim amendment before code (stop on breach; explain in the report)
    Container & model: S, mode:thread, model: default tier (dispatch-gates --tier: no path-derived mandate), effort: medium
    Clause-②: yes (widening): new optional host members and exports in @object-ui/mobile and four new i18n keys; nothing removed or narrowed
    Metadata-protocol: none
    Responsibility: the Console App lock row (read-only, opens the native screen); every lock write stays in the shell per mobile#145 ruling A
    Thread-read: 6595074906
    Premise: holds (at origin/main 7ba8b11f: the bridge reader is @object-ui/mobile nativeHost.ts (nativeHostCan + native* wrappers) with no app-lock members yet; the profile page is console ProfilePage.tsx; the contract is mobile PR #181 HYBRID-SHELL.md "App lock", not yet on mobile main)
    Serial constraints cleared: none blocking. Seat 3 #29735 (claim 6595193307) edits the same nativeHost.ts union, host interface, index.ts and test fake: whichever lands second merges main and keeps both sets of members. No open PR touches these files at claim time.

  3. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · zhuangjianguo · session_01QsR2jSM2R4osc3dyaqPHY1
    os-dev-report

    {
      "issue": 29748,
      "status": "done",
      "branch": "claude/project-thread-y37yg8",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/29798",
      "session": "session_01QsR2jSM2R4osc3dyaqPHY1",
      "premise_still_valid": true,
      "summary": "Profile page (/system/profile and account:profile_card) gains an App lock card, drawn only when nativeHostCan(useNativeHost(), 'openAppLockSettings'). It shows Off, On (immediately) or On with an Intl-named duration from getAppLock(), re-read on mount, visibilitychange to visible and window focus; a tap calls nativeOpenAppLockSettings(); no toggle and no write. @object-ui/mobile adds the two optional host members, NativeAppLock and the nativeGetAppLock / nativeOpenAppLockSettings wrappers (README updated); profile.appLock.{title,off,onImmediately,onAfter} in all ten packs. Contract read at objectstack-ai/mobile#181 head 77ded7bb (not on mobile main). One in-surface correction after the first run: the duration fell back to the machine locale (machineLocaleCensus-9909 red), now UI language then useDisplayLocale() (commit 75f435ad).",
      "tests": "Head 75f435ad. New ProfilePage.appLock-29748.test.tsx: 9 passed; on main's ProfilePage.tsx (7ba8b11f, tree-only restore, git diff HEAD empty after) 6 failed / 3 passed (every shell case red, 3 controls green). Ablation via ablation-replace --delete of the visibilitychange + focus listener lines: 1 failed / 8 passed (the re-read case), restored blob == HEAD. vitest packages/i18n/ packages/mobile/ + five ProfilePage suites: Test Files 109 passed, Tests 1633 passed, 13 skipped. turbo type-check console+mobile+i18n: 73/73. eslint on five changed code files: 0 errors, 1 pre-existing warning (ProfilePage name-sync set-state-in-effect).",
      "gates": "dispatch-gates --commands at 75f435ad: 35 families. 34 non-vitest run with exit captured before pipes, GITHUB_EVENT_PATH = the PR body: all exit 0. pnpm --dir ui exec vitest run scripts/: 170 files passed, 2 skipped, exit 0. check:new-line-citations (ui/): 0 new. Body gates before pr_create: check-changeset-no-major, check-adr-0087-registration, check-closing-keyword-parity, check-partof-closing-keyword all exit 0. CI check-runs: in_progress at report time. Not merged with main: 18 commits behind, git merge-tree clean.",
      "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
      "mcp_calls": "9 — GitHub MCP issue_read x5 (29748 get + comments, 29735, 29750), get_session, add_repo (read-only, mobile public); no MCP write tool",
      "api_writes": "2 — git push (branch); fleet-write pr_create (run 41582956881, PR #29798, body read back byte-identical). Plus this os-dev-report comment via post-stamped.",
      "open_questions": [],
      "security_findings": "none",
      "out_of_scope_findings": [
        "class: b · reach: named producer — objectstack-ai/mobile app/console.tsx openAppLockSettings: () => router.push('/app-lock-settings') pushes a native screen inside the same activity; HYBRID-SHELL.md 'Reading the app lock' says no event announces a change, and an Android WebView fires no visibilitychange for an in-activity push, so a Console that re-reads on visibility/focus can show the old state after the user returns from the settings screen until it remounts. Contract text: 'No bridge method changes the lock' / card: 'No event announces a change. Re-read getAppLock() when the profile page is shown.' Seam: shell:openAppLockSettings → renderer:console ProfilePage AppLockCard. Not reproduced on a device (no device here); measured only as the absence of any shell event in the contract. · dedupe words: appLockChanged, app lock event, getAppLock stale, visibilitychange WebView",
        "carrier: #29735 · serial merge on nativeHost.ts union/interface/index.ts/test fake, noted, not filed"
      ],
      "deviations": "Clause-② line copied as the seat's handshake reply spelled it ('Clause-②: yes (widening)'), not with the claim line's trailing explanation. PR has no assignees/reviewers (os-dev: none at pr_create; the harness's assignee/reviewer MCP step skipped as an MCP write). No PR subscription: re-runs and landing are the seat's."
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu

    Landed · 2026-11-03T05:55Z · PR #29798 merged through the merge queue as b62463f1 at 2026-11-03T05:54Z (GitHub's clock). ACCEPT 6596343019 and contract review 6596159679 (PASS) at head 75f435ad.

    probe before (b62463f1~1) now (origin/main)
    export function nativeGetAppLock in ui/packages/mobile/src/nativeHost.ts 0 1
    function AppLockCard in ui/apps/console/src/pages/system/ProfilePage.tsx 0 1

    Fixes #29748 closed this card. pm:dispatched comes off in the same stroke as this note. Serial: seat 3's #29803 (#29735) now merges main and keeps both member sets in NativeHostMethod, ObjectStackNative and index.ts. The follow-up is #29800, for the repo:mobile seat: the shell sends no app-lock change event, so the row can show the old state after an in-activity Android push.

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