Repository navigation
Seven smaller things a real user hits — items 1 and 6: legal tabs and boards shown to requesters, an empty landing page for lawyers - #104
Draft
objectstack-fleet[bot] wants to merge 1 commit into
Conversation
…ance boards An app opens on the first navigation entry the server still serves to the caller. Every position also holds clm_requester, so with 我的合同 listed first every audience opened on 我发起的: right for a business requester, empty for a lawyer. The four single-audience partitions now come first, then 我的合同 and 分析. A requester's served tree is unchanged. Legal Workbench and Finance Overview now carry the gate of the §05 partition they belong to (clm_legal.access / clm_finance.access). The server prunes a child on its own requiredPermissions, so a requester is no longer served those rows. Executive Overview stays ungated: the leadership rungs hold only clm_requester, so no spelling separates them from a requester. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HihZ11bQSqjCgjzHbpv4M1
This was referenced Oct 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #99. This PR covers items 1 and 6 of the card, as far as this app can take them. Items 2, 3, 4, 5 and 7 are not touched here, because open PRs hold their files, so #99 remains open for them. The view-switcher half of item 1 needs a platform capability that does not exist. It is reported below and not worked around.
What changed
One file:
src/apps/clm.app.ts. No view, object, dashboard, flow or translation file changes. Navigation labels are keyed by itemid, and noidchanged.nav_legal_workbenchnow carriesrequiredPermissions: ['clm_legal.access']andnav_finance_overviewcarries['clm_finance.access']. The group gate staysclm_requester.access. Executive Overview gets no row gate, on purpose (see open questions).Why this mechanism (measured on 17.7.0)
findFirstRoutefinds in the navigation the server served to that user. It walks in declaration order and skipsaction,urlandcomponentrows.homePageIdwas retired in spec 17.0.0, and nothing else chooses a landing page. Every position also bindsclm_requester(src/security/bind-position-sets.ts), so My Contracts survived for everyone. Because it was listed first, it was every audience's first screen.filterAppForUserWithReason(@objectstack/rest17.7.0) prunes each child on its ownrequiredPermissionsusingevery(...). One capability per row therefore needs no OR.clm_requester, still open on 我发起的.Audience matrix: what
GET /api/v1/meta/app/clmservesBefore is
46e65f0(main). After iscad612f(this branch). Same database, same six accounts.clm_requesterset, no position)my_contractsmy_contractsclm_executive)my_contractsmy_contractsclm_legal_counsel)my_contractslegal_intakeclm_finance_controller)my_contractsall_payment_plansclm_records_manager)my_contractspending_executionclm_admin)my_contractsclm_approval_rulePositive control for the two new gates: Legal Counsel 1 is served Legal Workbench and Finance Controller 1 is served Finance Overview. Neither spelling hides its row from its own audience.
validatealso prints no "requiredPermissions references capability … registered nowhere" warning.Browser evidence
Chromium 1194 at 1440×900, each persona signed in through the console's own login form, port 3499.
Boot.
pnpm demo -- --port 3499printedPlugins: 41 loaded, with nodegraded capabilitiesand nono such table. The warnings were the known set: six scheduled flows unbound by deployment policy, analyticsadmitObjectRead, OAuth over plain HTTP, and the seeder's background budget. On the second boot there were also unresolvedBusiness Requester 2/3andLegal Counsel 2names, which are accounts I did not create.Before (
46e65f0)./_console/apps/clm/clm_contract/view/my_contracts.my_contractsURL, and the page reads "No matching records".After (
cad612f)./_console/apps/clm/clm_contract/view/legal_intake("Awaiting Intake").filteronstatusequalssubmitted) answered200,total=6.my_contracts, whoseowner_idrequest answered200,total=43.all_payment_plans(total=300).pending_execution(total=6).clm_approval_rule(total=6).my_contracts(total=0, see open questions).401 GET /api/v1/auth/get-session, the session probe before sign-in;view:calendarandview:timelinebare-name fallback)./_console/apps/clm/dashboard/legal_workbenchstill renders the board. Its numbers are row-scoped (Awaiting Intake 3, the requester's own contracts). The row gate hides the entry. It is not a gate on the dashboard.The dev agent keeps the screenshots locally and hands them to the seat. They are not committed: they are outside this card's file surface, and the write budget allows no evidence branch.
Gates (on
cad612f)pnpm verifychains the four gates with&&. It ran through the shared verify lock, which printedVERDICT command-exit 0.validate:
lint (the six suggestions are the existing
approval-approvers-may-resolve-emptyones oncontract_approval):typecheck:
tsc --noEmitprinted nothing and exited 0 (the&&chain went on to the next gate).lint:i18n-gate:
Platform findings (reported to the seat, not filed, no workaround)
P1. A list view and a dashboard carry no audience gate. So the view switcher shows every audience's views, and a dashboard hidden from the navigation still opens.
clm_contractswitcher lists all 11 list views, including the legal desk's, finance's and records'. As that requester,GET /api/v1/meta/viewreturns all 11clm_contractview items. The Legal Workbench opens by URL even though its navigation row is not served.listViews,mineandteam_only, and point a navigation item gatedrequiredPermissions: ['x.access']atteam_only.x.access.team_onlyis still a tab in the switcher.type: 'dashboard'row behaves the same way: hidden from the navigation, but its URL opens.ListViewSchemahas 50 top-level keys. The only access-shaped one issharing(typepersonal or collaborative, pluslockedBy).DashboardSchemahas norequiredPermissionsand novisible.ViewTabBargets every list-family view of the object from the adapter'slistViews(), with no audience filter.requiredPermissionsis.@objectstack/spec,@objectstack/consoleand@objectstack/rest17.7.0.P2.
requiredPermissionshas no any-of form. Every layer checksevery(...), so a row cannot be served to "legal or admin". Here that is why CLM Admin 1 is no longer served Legal Workbench and Finance Overview. Version 17.7.0. The app's analytics comment already records the AND semantics. I did not search upstream for an existing issue; that check is the seat's.Acceptance notes
clm_adminnow see their own group above My Contracts. A requester and the two leadership rungs are served exactly the tree they had before.clm_adminhad the same defect and the same cause, and the one reorder fixes all four. This is the same defect class in the same file, and nothing new needs verifying.Open questions (for the seat)
requiredPermissionsspelling can serve the board to leadership and not to requesters.clm_executiveandclm_general_manager. That is a §04 change and the maintainer's call.visiblepredicate on positions. It is still served, and it ties the navigation to position names.componentrow thatfindFirstRouteskips.Generated by Claude Code