mirror of
https://github.com/mvschwarz/openrig.git
synced 2026-11-07 22:58:42 -10:00
Revert "feat(mcp): a Cloud customer can't hand a task to a caller seat"
This reverts commit 78f426ba76.
The caller-seat create refusal waits on a product decision, so it stays
out of this merge. It comes back by reverting this commit. A customer's
task can go to any seat of its rigs on this instance, as with the first
commit; the read rule that ignores items from caller-shaped seats is
unchanged.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
692d6b2b8d
commit
0f93cfed9b
2 files changed
+6
-8
No files matched your search
@@ -264,14 +264,13 @@ function scopeFor(access: McpAccess, seatOf: () => string | undefined): Scope {
|
||||
}
|
||||
|
||||
/** Cloud names a customer's caller seat cus-<id>-caller@<rig>. v1 marks no seat as a caller, so an item from a seat of
|
||||
* this shape is never the team's question to a customer, and a customer can't hand a task to one. The shape never
|
||||
* grants anything. */
|
||||
* this shape is never the team's question to a customer. The shape never grants anything. */
|
||||
const CALLER_SHAPED = /^cus-.+-caller@[^@]+$/;
|
||||
|
||||
/** A Cloud customer grant (openrig.cloud.grant/v1): a requester, narrower than a work grant. The grant's own seat is the
|
||||
* only caller. It may hand tasks to its rigs' team seats (never a caller-shaped seat, a person or another host's
|
||||
* seat), read the items it sent and the team's questions to it (never team-internal or another caller's items), follow
|
||||
* a handed-on item only where it came back to it, and read the artifacts of its own items under its named roots. */
|
||||
* only caller. It may hand tasks to its rigs' seats (never a person or another host's seat), read the items it sent and
|
||||
* the team's questions to it (never team-internal or another caller's items), follow a handed-on item only where it
|
||||
* came back to it, and read the artifacts of its own items under its named roots. */
|
||||
function customerScope(access: McpAccess, seatOf: () => string | undefined): Scope {
|
||||
const rigs = new Set(access.rigs);
|
||||
const caller = (value: unknown): boolean => typeof value === "string" && value !== "" && value === seatOf();
|
||||
@@ -291,8 +290,7 @@ function customerScope(access: McpAccess, seatOf: () => string | undefined): Sco
|
||||
owner: () => false,
|
||||
rig: (name) => typeof name === "string" && rigs.has(name),
|
||||
root: (name) => typeof name === "string" && access.roots.includes(name),
|
||||
// A task goes to the team: never to the caller itself or to another caller-shaped seat, which v1 can't tell apart.
|
||||
destination: team,
|
||||
destination: member,
|
||||
successor: caller,
|
||||
artifact: (row) => caller(field(row, "sourceSession")),
|
||||
paths: false,
|
||||
|
||||
@@ -199,7 +199,7 @@ describe("rig mcp serve --http --cloud-grants on the daemon's routes", () => {
|
||||
const served = await listen();
|
||||
const asCustomer = await connect(served.url);
|
||||
const before = rows();
|
||||
for (const destination of ["cus-otherone01-caller@team-a", CALLER, "lead@team-b", "alex@external", "lead@team-a@elsewhere"]) {
|
||||
for (const destination of ["lead@team-b", "alex@external", "lead@team-a@elsewhere"]) {
|
||||
expect((await asCustomer("rig_queue_create", { destination, body: "not allowed" })).structured).toMatchObject({ ok: false, code: "out_of_scope" });
|
||||
}
|
||||
expect(rows()).toBe(before);
|
||||
|
||||
Reference in new issue
Block a user