Background
#330 settles what --tail N means across the CLI: the newest N entries. log, audit, and webftp already behave that way—each passes tail as the limit to api.FetchCursorPages, and the Elasticsearch-backed endpoints sort -date descending, so the first page holds the newest rows.
Two commands break that contract in two different ways.
1. websh ls --tail returns the oldest sessions
cmd/websh/websh_list.go:29-31 fetches every page and then slices the physical end of the list:
if tail > 0 && tail < len(sessionList) {
sessionList = sessionList[len(sessionList)-tail:]
}
The sessions endpoint sorts newest first (SessionViewSet.ordering = ['-added_at'] in alpacon-server websh/api/views.py:130), so the end of that list is the oldest sessions. alpacon websh ls --tail 5 reports the five oldest sessions while the flag help says "Number of sessions to show".
Fix: slice the head (sessionList[:tail]), since the list is already ordered newest first.
2. exec ls --tail cannot exceed one page
api/event/event.go:213-225 sends page_size=tail in a single request and never looks at ListResponse.Next:
params := map[string]string{}
if pageSize > 0 {
params["page_size"] = fmt.Sprintf("%d", pageSize)
}
responseBody, err := ac.SendGetRequest(utils.BuildURL(getEventURL, relativePath, params))
The server caps a page at 100 (max_page_size in alpacon-server api/pagination.py), so alpacon exec ls --tail 500 silently returns 100 entries. This is the same defect shape as #330.
Fix: reuse the limit-bounded helper #330 adds to api/pagination.go, so no second page loop is written:
endpoint := path.Join(getEventURL, relativePath)
events, err := api.FetchPagesUpTo[EventDetails](ac, endpoint, nil, tail)
api/event/chunks.go:38 already assembles an endpoint this way before calling api.FetchAllPages, so the shape matches existing code.
Order
Part 2 depends on #330 landing first—it calls the helper that PR introduces. Part 1 is independent and can go first.
References
cmd/websh/websh_list.go:29-31—tail slice on a descending list
api/event/event.go:213-225—single request, Next ignored
api/pagination.go—FetchAllPages, FetchCursorPages
#330—note ls pagination and the --tail contract
Background
#330settles what--tail Nmeans across the CLI: the newest N entries.log,audit, andwebftpalready behave that way—each passestailas the limit toapi.FetchCursorPages, and the Elasticsearch-backed endpoints sort-datedescending, so the first page holds the newest rows.Two commands break that contract in two different ways.
1.
websh ls --tailreturns the oldest sessionscmd/websh/websh_list.go:29-31fetches every page and then slices the physical end of the list:The sessions endpoint sorts newest first (
SessionViewSet.ordering = ['-added_at']in alpacon-serverwebsh/api/views.py:130), so the end of that list is the oldest sessions.alpacon websh ls --tail 5reports the five oldest sessions while the flag help says "Number of sessions to show".Fix: slice the head (
sessionList[:tail]), since the list is already ordered newest first.2.
exec ls --tailcannot exceed one pageapi/event/event.go:213-225sendspage_size=tailin a single request and never looks atListResponse.Next:The server caps a page at 100 (
max_page_sizein alpacon-serverapi/pagination.py), soalpacon exec ls --tail 500silently returns 100 entries. This is the same defect shape as#330.Fix: reuse the limit-bounded helper
#330adds toapi/pagination.go, so no second page loop is written:api/event/chunks.go:38already assembles an endpoint this way before callingapi.FetchAllPages, so the shape matches existing code.Order
Part 2 depends on
#330landing first—it calls the helper that PR introduces. Part 1 is independent and can go first.References
cmd/websh/websh_list.go:29-31—tail slice on a descending listapi/event/event.go:213-225—single request,Nextignoredapi/pagination.go—FetchAllPages,FetchCursorPages#330—note lspagination and the--tailcontract