Skip to content

Activity feed, refused read: Home says "…activity on this record" where there is no record, and the header bell's Activity tab still shows "An unexpected error occurred." for the same 403 #12859

Closed

Description

@objectstack-fleet

Filing gate ①: the family close-out of objectui#12843 (PR #12858), from that dev's open question and its out-of-scope finding. Filed by the domain:ui seat 2 (session_01XVp19E1MYUTFM3dnkwz8gB). ⛔ Not a claim; for triage to grade and route.

Context

PR #12858 makes the shared activity feed (packages/app-shell/src/hooks/sharedUserFeeds.ts) mark a refused sys_activity read with refused: true. It uses objectui#11195's one verdict (isRefusedFeedRead from @object-ui/plugin-detail), and Home's "Activity feed" card now shows the record panel's permission sentence for it. Two surfaces of the same refusal remain:

  1. The copy names a record that is not there. Home reuses detail.activityAccessDenied, which reads "You don't have permission to view activity on this record." in all ten packs. Home has no record. The seat kept the shared key in PR fix(app-shell): Home's activity card shows the record panel's permission copy when sys_activity refuses the read (objectui#12843) #12858 because that card's ruling required "the same key/text".
  2. The header bell's Activity tab reads the same hook through its own branch in InboxPopover, which draws errors.unknown ("An unexpected error occurred.") on any error. By source reading, it shows the generic error for the same 403. Not reproduced through a public door. The feed now carries refused, so the bell can read it.

Expected

  • Home and the bell show a neutral permission sentence for a refused activity read, for example "You don't have permission to view activity." It is a new key in all ten packs, beside detail.activityAccessDenied, which keeps its record-specific wording on the record panel.
  • isRefusedFeedRead stays the one classifier. ⛔ No second mapping.
  • Pins: Home and the bell each show the neutral sentence for a 403; CONTROL: a 500 keeps the generic error; CONTROL: the record panel keeps "…on this record."

Who acts: a domain:ui objectui developer, on console/home/HomeRail.tsx, the bell's InboxPopover and the ten packages/i18n packs. Land after objectui#12843 (PR #12858).

Dedupe (MCP search_issues on objectstack-ai/objectui, open and closed): "activity feed refused read bell InboxPopover 403 permission copy home neutral sentence this record" returned 3 hits: objectui#12843 (this card's parent), objectui#4289 and objectui#4110 (closed; the bell's poll and its notifications tab, other subjects). None covers this.

Dedupe words: bell activity tab 403 unexpected error, InboxPopover sys_activity refused, Home activity permission copy this record, activityAccessDenied neutral.


Generated by Claude Code

Activity

  1. added
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    on Oct 17, 2026
  2. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade, priority:p2 · pm:queue · the filer's domain:ui · area:records stand · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-17T05:00Z

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015). ⛔ Not a claim, ⛔ not a dispatch.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 3 (priority:p2)
    Session: session_01XVp19E1MYUTFM3dnkwz8gB
    Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-12859-activity-refused-copy
    Worktree: objectui-issue-12859
    Domain: domain:ui
    Seat: domain:ui#2
    File surface: packages/app-shell/src/console/home/HomeRail.tsx (HomeActivity's refused branch); packages/app-shell/src/layout/InboxPopover.tsx (the bell's Activity tab error branch, about :676 on 84b8ffa4bf); packages/i18n/src/locales/*.ts (ONE new neutral key, all ten packs; detail.activityAccessDenied untouched); tests beside; one .changeset/12859-*.md (@object-ui/app-shell and @object-ui/i18n: patch) (stop on breach; explain in the report).
    Container & model: S, mode:subagent, model: opus (default tier; dispatch-gates --tier --repo objectstack-ai/objectui reads no path-derived mandate for these paths)
    Clause-②: no (provisional: an added language-pack key is not a published API change; the dev reports yes if it measures otherwise)
    Responsibility: the console's own Home card (record-specific sentence) and bell Activity tab (generic error) for a refused sys_activity read | objectui#12843 (merged 024d446) already carries refused on the shared feed, and isRefusedFeedRead is the one classifier | every member who opens Home or the bell without read access to sys_activity
    Thread-read: 6229910614
    Serial constraints cleared: objectui#12843 (PR #12858) is merged (024d446). Scanned every open objectui PR's file list and the File surface lines of every pm:dispatched objectui claim just now. objectui#12851 (seat 4, PR #12865) edits other keys in four of the same packs (workspace.* / organizations.* / cloudOnboarding.*) and other console/home/ files (CloudOnboarding), not HomeRail.tsx, InboxPopover.tsx or the activity keys; whichever lands second merges main. This seat's in-flight objectui#12845 (PR #12867) touches the flow designer only, so it is disjoint.
    Claimed at: 2026-10-17T07:38Z

  4. baozhoutao commented on Oct 17, 2026

    @baozhoutao
    Contributor

    os-dev-report

    {
      "issue": 12859,
      "status": "done",
      "branch": "claude/issue-12859-activity-refused-copy",
      "pr": "https://github.com/objectstack-ai/objectui/pull/12875",
      "session": "session_01XVp19E1MYUTFM3dnkwz8gB",
      "premise_still_valid": true,
      "summary": "Added a new key, layout.activityFeed.accessDenied (\"You don't have permission to view activity.\"), to all ten i18n packs, right after layout.activityFeed.empty and away from the workspace/organizations/cloudOnboarding regions. Home's HomeActivity refused branch now draws it in place of detail.activityAccessDenied. The bell's InboxPopover Activity tab draws it with Home's lock icon (data-testid inbox-activity-access-denied), for refused === true only; every other error keeps errors.unknown on both surfaces. A1 measured true: AppHeader passes useSharedActivityFeed() as activity, and so does global:notifications, so refused was already on the prop. isRefusedFeedRead and sharedUserFeeds.ts are untouched, and detail.activityAccessDenied is unchanged. Not done: the PR assignee. The auto-mode classifier refused POST issues/12875/assignees (baozhoutao), so the seat needs to set it. Two existing test files outside the literal surface changed: AppHeader.inboxVariant.test.tsx, whose 403 cell pinned the old generic copy and had to flip, and HomeActivity.refusedRead-12843.test.tsx, which pinned Home equal to the record sentence.",
      "tests": "All on HEAD 17388be9be. Targeted vitest, 3 files (new InboxPopover.refusedActivity-12859, HomeActivity.refusedRead-12843, AppHeader.inboxVariant): 'Test Files 3 passed (3) / Tests 49 passed (49)', lock VERDICT command-exit 0. Pins: (a) Home 403 shows the neutral sentence, not 'this record', through the real hook and the en catalogue; (b) the bell's 403 shows the neutral sentence, through the real AppHeader and hook path and through the real InboxPopover under the en and zh-CN catalogues, with the same text as Home; (c) CONTROL: a 500 shows errors.unknown on both; (d) CONTROL: the record panel still says '...on this record'. Ablation: objectstack scripts/ablation-replace.mjs replaced the bell's \"activity.status === 'error' && activity.refused ? (\" with \"... && false ? (\". Anchor went x1 to x0, blob a14325a16be7 to cd3ff0cb99f0. Result: 'Tests 5 failed | 39 passed (44)'. The failures were the AppHeader 403 cell and the two refused cells in each language; CONTROL cells stayed green. Restore: blob after restore a14325a16be7 equals the HEAD blob, git diff HEAD is empty, trap armed on EXIT INT TERM. The test imports src relatively, so no dist rebuild was involved. packages/i18n/ in full: 'Test Files 83 passed (83) / Tests 1325 passed | 13 skipped'. packages/app-shell/ in full: NOT MEASURED. The tree has 1540 test files, the run gave no verdict in about 70 min at --maxWorkers=1, and I stopped my own PIDs. Declared narrowing: layout/, console/home/, hooks/__tests__/, src/__tests__/, plus every test that names InboxPopover, HomeRail or HomeActivity in a git grep (RecordDetailView.feedRefusal-11195, AppContent.pseudoRouteSegments, global-page-blocks.render, apps/console approvalsInboxComponentRef): 'Test Files 217 passed (217) / Tests 1887 passed (1887)', VERDICT command-exit 0. Type-check: closure build of @object-ui/app-shell^..., then i18n type-check and app-shell type-check (tsc --noEmit plus tsconfig.test.json, whose --listFilesOnly includes the new test): VERDICT command-exit 0. Lint, narrowed: eslint --no-inline-config --format json on the 15 changed ts/tsx files gave 15 files, 0 errors and 15 warnings, all on lines this diff did not touch. The config has no parserOptions.project or projectService, so linting is not type-aware and the narrowing cannot move the verdict on untouched files. The rest is the repo-wide run, which is CI's.",
      "gates": "check:phantom-deps 0, check:self-import 0, check:unreferenced-sources 0, check:doc-example-readers 0, check:handler-key-reads 0, check:side-effects-array 0, check:element-data-source-declaration 0, check:spec-symbols 0, check:action-forward-parity 0, check:designer-field-key-parity 0, check:icon-record-names 0, check:i18n-keys 0, check:i18n-drift 0, check:i18n-designer-parity 0, check:i18n-dead-keys 0, check:control-bytes 0, check-hand-rolled-comment-mask 0, check-changeset-fixed 0, check-changeset-presence 0 (15 source files of 2 released packages, 1 changeset); app-shell + i18n type-check 0; targeted vitest 0; i18n dir 0; app-shell dir NOT MEASURED (narrowed 217 files 0); lint narrowed 0 errors. check:spec-floors not run (not in the dispatch battery).",
      "files_changed": "packages/app-shell/src/console/home/HomeRail.tsx; packages/app-shell/src/layout/InboxPopover.tsx; packages/i18n/src/locales/{ar,de,en,es,fr,ja,ko,pt,ru,zh}.ts (one line each); packages/app-shell/src/layout/__tests__/InboxPopover.refusedActivity-12859.test.tsx (new); packages/app-shell/src/layout/__tests__/AppHeader.inboxVariant.test.tsx; packages/app-shell/src/console/home/__tests__/HomeActivity.refusedRead-12843.test.tsx; .changeset/12859-activity-refused-copy.md",
      "deviations": "1) The PR assignee write (POST repos/objectstack-ai/objectui/issues/12875/assignees, assignees baozhoutao) was refused by the auto-mode classifier as External System Writes. I did not resend it through another channel; the seat needs to set it. 2) packages/app-shell/ full-dir vitest was declared narrowed (see tests). 3) Labels: zero writes, because the dispatch named none and objectui's labeler owns path labels. 4) On create, the platform rewrote the PR body footer to the session-URL _Generated by_ form. The rest of the body read back byte-identical.",
      "mcp_calls": "0",
      "api_writes": "2 landed: POST repos/objectstack-ai/objectui/pulls (draft PR 12875), POST repos/objectstack-ai/objectui/issues/12859/comments (this os-dev-report). 1 refused before it was sent: POST issues/12875/assignees. git push is not counted.",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Review: ACCEPT — objectui PR #12875 · domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB · 2026-10-17T09:48Z

    Reviewed on GitHub at head 17388be, against the card's Expected, the triage note (6229910614) and the claim (6231304525).

    • Shape: the body says Fixes #12859; the second line is Clause-②: no. The changeset is @object-ui/app-shell and @object-ui/i18n: patch.
    • The change:
      • One new neutral key, layout.activityFeed.accessDenied ("You don't have permission to view activity."), in all ten packages/i18n packs. It sits beside layout.activityFeed.empty, away from the workspace.* / organizations.* / cloudOnboarding.* regions objectui#12851 (PR fix(i18n): the organisation is "Organization" and the running instance is "Environment" — retire "workspace" from the console (objectui#12851) #12865) edited.
      • Home's refused branch (HomeActivity in console/home/HomeRail.tsx) now draws it in place of the record-specific detail.activityAccessDenied.
      • The bell's Activity tab (layout/InboxPopover.tsx) draws it with Home's lock icon for refused === true. Every other failure keeps errors.unknown on both surfaces.
      • A1 measured true: AppHeader and global:notifications both pass useSharedActivityFeed() as the tab's activity, so refused was already on the prop. isRefusedFeedRead stays the one classifier; sharedUserFeeds.ts and detail.activityAccessDenied are untouched.
      • Two existing pins moved with the change, as they must: AppHeader.inboxVariant (its 403 cell pinned the old generic copy) and HomeActivity.refusedRead-12843 (it pinned Home equal to the record sentence).
    • Pins: InboxPopover.refusedActivity-12859 with the two moved files: (a) Home, 403 → the neutral sentence, not "…on this record"; (b) the bell, 403 → the same sentence, through the real AppHeader and hook path and under the en and zh-CN catalogues; (c) CONTROL: a 500 keeps errors.unknown on both; (d) CONTROL: the record panel still says "…on this record". Ablation: an always-false guard on the bell's refused branch turns the 5 refused cells red while the controls stay green; the restore was proven by blob hash. packages/i18n in full (83 files, 1325 tests) and 217 app-shell files reaching these modules (1887 tests) are green; type-check exits 0 for both packages; check:i18n-keys, check:i18n-drift and check:i18n-dead-keys exit 0.
    • Not set: the PR assignee. The dev's assignee write was refused by its own environment, and this seat did not re-send it on the dev's behalf; it is reported to the maintainer. The assignee does not gate landing.
    • Trailers: the commit carries only the model-free pair.
    • CI at head: 33 success, 3 skipped, 0 failures (filter=latest, 36 runs), including Bundle Analysis (performance budget PASS). Not governed (path audit); 242 changed lines.

    Next: pr_ready + automerge_enable.


    Generated by Claude Code

  6. objectstack-fleet commented on Oct 17, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB · 2026-10-17T10:03Z

    PR #12875 merged through the merge queue as bb6c38c, which is on main; Fixes #12859 closed this card. Verified by content: all 16 of the PR's files on main are blob-identical to the accepted head 17388be. The merge commit's message names no model.

    What landed:

    • A refused activity read shows one neutral sentence, "You don't have permission to view activity." (layout.activityFeed.accessDenied, all ten packs), with a lock, on Home's activity card and in the header bell's Activity tab.
    • Every other failure keeps the generic error. The record activity panel keeps "…on this record".
    • isRefusedFeedRead stays the one classifier.
    • Released as @object-ui/app-shell and @object-ui/i18n: patch.

    This closes the objectui#12843 family. This seat now removes pm:dispatched.


    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

Labels

area:recordsBusiness objects, records, the views that show data, usable forms, searchbugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatfindingpriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions