bus, webui, cli: the Console shows the reply to a web send (#1575)
Row 81. The broker gains a `replies` read verb for human and reader
sessions: `{id}`, a message UUID, returns that business's messages whose
in_reply_to is the id, oldest first, at most 50, and writes no
deliveries row, so the reply still reaches the next `mosaic talk`. An
unknown id refuses message-not-found. The Console serves it through
BUS_VERBS with an id check, and the Sent receipt shows the replies to a
web send. The cli's talk timeout message and README now say the reply
may still come and the next `mosaic talk` prints it.
Dewey's round 2, candidate manifest 3ce7527f, base 1e5f5958, a rebase
after row 61. Approved by Darkwing (27783 round 1, 27821 round 2).
Sage's gate green 19:25:18Z to 19:30:39Z. Live at the next bus restart
(the broker verb) and Console restart (the view), bus first.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -40,6 +40,8 @@ const GATED = new Set([
|
||||
const CLOSED = "('resolved','withdrawn','expired')";
|
||||
// How many closed decisions `decisions` with list 'recent' returns, newest close first.
|
||||
export const RECENT = 50;
|
||||
// How many replies `replies` returns, oldest first.
|
||||
export const REPLIES = 50;
|
||||
export const TASK_VERBS = Object.freeze(ACTIONS.filter((a) => a.startsWith('task.')));
|
||||
const SELF_KINDS = new Set(['task.created', 'task.assigned', 'task.state', 'task.closed', 'task.conflict']);
|
||||
const POLL_KINDS = new Set([
|
||||
@@ -492,7 +494,7 @@ export class Broker {
|
||||
if (!object(args)) fail('invalid-request');
|
||||
this.#secretCheck(args);
|
||||
return this.#store.transaction(() => {
|
||||
if (s.reader && !['inbox', 'agents', 'tasks', 'trail', 'decisions', 'credentials'].includes(request.verb))
|
||||
if (s.reader && !['inbox', 'agents', 'tasks', 'trail', 'decisions', 'credentials', 'replies'].includes(request.verb))
|
||||
fail('read-only');
|
||||
const result = this.#dispatch(s, request.verb, args);
|
||||
this.#secretCheck(result);
|
||||
@@ -906,6 +908,22 @@ export class Broker {
|
||||
};
|
||||
});
|
||||
}
|
||||
// Row 81 (#1575): the replies to a message, for the Console's web-send receipt. Human and
|
||||
// reader sessions only, like decisions. It writes no delivery or read row, so a reply it
|
||||
// lists still reaches the next `mosaic talk`. An id naming no message in the business
|
||||
// refuses message-not-found, as message.send does for in_reply_to; trail would return [].
|
||||
case 'replies': {
|
||||
if (!s.human && !s.reader) fail('human-required');
|
||||
keys(a, ['id'], ['id']);
|
||||
identifier(a.id);
|
||||
if (!this.#store.get('SELECT id FROM messages WHERE id=? AND business=?', a.id, s.business))
|
||||
fail('message-not-found');
|
||||
return this.#store.all(
|
||||
`SELECT * FROM messages WHERE business=? AND in_reply_to=? ORDER BY seq LIMIT ${REPLIES}`,
|
||||
s.business,
|
||||
a.id,
|
||||
);
|
||||
}
|
||||
default:
|
||||
fail('unknown-verb');
|
||||
}
|
||||
|
||||
@@ -7,5 +7,6 @@ export function views(client) {
|
||||
trail: (subject) => client.call('trail', { subject }),
|
||||
decisions: (list) => client.call('decisions', { list }),
|
||||
credentials: () => client.call('credentials'),
|
||||
replies: (id) => client.call('replies', { id }),
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user