Desk: a read of an oversize fork is 422 fork_too_large (#42)

This commit is contained in:
Heimdall 2026-11-11 01:35:07 +00:00
commit 8385eca00f
4 changed files with 32 additions and 3 deletions

View file

@ -151,7 +151,7 @@ public static class DeskRefusals
[RequestIdConflict] = (409, "request_id_conflict: this request_id was used for a different body"),
};
// fork_too_large (Libby's ruling) is list-only and names its fork, so it is built here, not read from the table.
// fork_too_large (Libby's ruling) names its fork, so it is built here, not read from the table.
// Not a literal const: the pinned vectors' doorRefusals do not name it yet, and the schema test pins literals to them.
public static string ForkTooLarge => "fork_too_large";
@ -164,6 +164,10 @@ public static class DeskRefusals
? $"fork_too_large: fork {forkId} (order {order}) is too large for a page; continue with cursor c{order}"
: $"fork_too_large: fork {forkId} (order {order}) is too large for a page; the list has reached its end");
// A read of an oversize fork: the same permanent refusal, naming the fork and nothing to page.
public static DeskRefusal ForkTooLargeDocument(string forkId) => new(
DeskSchemas.Refusal, ForkTooLarge, $"fork_too_large: fork {forkId} is too large to return");
public static bool IsKnown(string code) => Table.ContainsKey(code);
public static int StatusOf(string code) => Table[code].Status;

View file

@ -189,6 +189,10 @@ public static class DeskEndpoints
{
await WriteJsonAsync(http, 200, IsDecider(context) ? entry : DeskNotes.Strip(entry));
}
else if (found is DeskReadOutcome.ForkTooLarge(var largeFork))
{
await WriteJsonAsync(http, DeskRefusals.ForkTooLargeStatus, DeskRefusals.ForkTooLargeDocument(largeFork));
}
else if (found is DeskReadOutcome.NotFound(var readCode) && DoorMayRefuse(readCode) && readCode != DeskRefusals.RequestIdConflict)
{
await WriteRefusalAsync(http, ReadListCode(readCode));

View file

@ -35,6 +35,9 @@ public abstract record DeskReadOutcome
public sealed record Found(ForkEntry Entry) : DeskReadOutcome;
public sealed record NotFound(string Code) : DeskReadOutcome;
// The fork is too large to return: permanent, and nothing to page, so no order or cursor.
public sealed record ForkTooLarge(string ForkId) : DeskReadOutcome;
}
// The list request the desk's query string stands for. Mind is the route's, resolved against the configured list.
@ -47,7 +50,7 @@ public abstract record DeskListOutcome
public sealed record NotListed(string Code) : DeskListOutcome;
// The next fork is too large for any page: the page holds nothing past the cursor. The client continues with
// cursor c<Order>; at Order 0 it has reached the end. List only: no other call can be refused this way.
// cursor c<Order>; at Order 0 it has reached the end. A read of such a fork has its own outcome (no order).
public sealed record ForkTooLarge(string ForkId, int Order) : DeskListOutcome;
}