project: drop unreachable rawHosts/rawTools fields on Project
The struct literal carried two unexported fields with
db:"raw_hosts" / db:"raw_tools" tags, but the actual scan
target is the local rawRow struct in List() that does the
GROUP_CONCAT split + dedupe before assigning Hosts/Tools.
sqlx silently ignores the unexported fields, so they never
held any data; they just confused the next reader of the
type definition.
project: add /api/v1/projects aggregation; sessions: add ?cwd= filter
- session.ListFilter gains Cwd *string; List appends working_dir = ?
clause between Host and Since in fixed order (parameterised, column
name is a literal)
- session.Handler reads ?cwd= and threads it to filter.Cwd; empty
string treated as absent, consistent with other optional filters
- new package internal/domain/project:
- Repository.List groups sessions by non-NULL working_dir in a single
SQL round-trip; correlated subquery picks top_tool with tie-broken
by tool ASC; Hosts/Tools deduped and sorted in Go after
GROUP_CONCAT
- Handler mounts GET /projects; resolveScope/clampLimit/clampOffset
duplicated from session handler; ?owner= admin gating identical
- server.Server gains Projects *project.Handler inject field; mounted
in /api/v1 Route block
- main.go and e2e test register projectRepo + projectHnd with steward