Domain migration. Depends on PAR-413 (reference domain). Copy its structure. Commandments 6, 8, 10, 12, 20, 24 and 25.
io.paradaux.tasklie.taskstasks/store/PostgresTaskSystem into tasks/persistence/ (one class per table: issues, issue_label, issue relations), tenant-scoped, mapped to records in tasks/model.ListIssues: filters, grouping, ordering. Groups need true totals per group, fixing PAR-373.SearchIssuesGetIssue: with sub-issue tree, labels, votes, source and development linksListBoardTasksFacade read methods.GET /api/public/w/{ws}/issues (filters as query params, cursor pagination), /issues/{ref}, /issues/{ref}/children and /board. Regenerate the OpenAPI spec.apps/web/domains/issuesdata/server.ts and data/hooks.ts for list, detail and board.Orchestrator review of #47: CI is green and the branch is up to date with rebuild. The rest looks good, including the per-group true totals (PAR-373), the MCP tools keeping the same names and behaviour, and the ratchet going down (ArchUnit store 1928 → 1865, ESLint suppressions 89 → 76). Sent back for one security fix: canSeePrivateTeams trusts any API key not named "service". That's fail-open. A key with no workspace of its own, coming in through the web, could see private teams in a public workspace. It needs to decide from whether the key belongs to this workspace or the context is internal (MCP, job or GitHub), not from the key's name, and it needs tests both ways. I'll merge once that's fixed.
Merged into rebuild as #47 (5b9403e) after the security fix. Who can see private teams is now decided once, when the workspace is resolved, and carried on the request context (RequestContext.privateTeams). It never depends on a key's name, and anything not listed below gets public teams only.
Who sees private teams:
Ratchet: ArchUnit store 1928 → 1865, ESLint suppressions 89 → 76. Handoffs for PAR-415 (writes), PAR-423 (guest transport) and PAR-417 (JdbcIssueLookupRepository TODO) are in the agent report above.
Plan (branch par-414-issues-reads, from rebuild):
Backend, new domain package
io.paradaux.tasklie.issues(named to match webdomains/issues):model(IssueSummary, IssueDetail with sub-issue tree, labels, votes, dev links, group page),persistence(JdbcIssueRepository: all issue READ SQL incl. issue_label join; keyset cursor per group; true per-group totals via one aggregate; tenant_id on every query),usecase(ListIssues, SearchIssues, GetIssue, ListBoard, ResolveFilters),IssuesFacade(read methods, issue.read, readOnly tx),api/IssueQueryController(GET list, groups/{group}, search, {ref}, {ref}/children, board) andmcp/IssueMcpTools(tasklie_get/list/search_task, same names). Writes stay in the legacy IssueApiController until PAR-415. Visibility of private teams for non-members is decided in the facade through the WorkspaceAccess port (small new method). Web:domains/issues(data/server.ts, data/hooks.ts, types aliased from generated schema), replace Kysely reads behind issues list, board, issue detail, home search; list gets per-group totals + Show more (PAR-373) with collapsed groups not loading rows. Ratchet: report frozen-store and ESLint-suppression deltas in the PR.