Repository navigation
fix(operator-queue): machine keys read the queue without a person's identity (abilityai/trinity-enterprise#715) - #3090
Merged
Merged
Conversation
…dentity (Abilityai/trinity-enterprise#715) The operator queue's reads handed agent-, system- and other machine keys the email of the person who answered an ask and of the person it was for, and the file write-back put the answerer's email into the agent's own queue file. - GET /api/operator-queue, /{id} and /agents/{name}: a non-person principal gets an ALLOWLIST projection (`_MACHINE_ROW_FIELDS`) with no responded_by_id/responded_by_email, addressed_to_email (file rows too), disposed_by_email or resolved_to. A person (JWT or their own user-scoped key, `is_person_principal`) still reads the whole row. - The platform's heads-ups ABOUT a person (the ent#499 problem report: a client's email and verbatim words; the ent#308 inbox collision: client addresses, an email-slug id) are not returned to a machine at all (skipped on list, 404 on the item route). `portal-inbox-collision-` joins the reserved prefixes, so that alert also stays out of the agent's file, its resume turn and the Execution Context "Ended asks" line. - The file write-back no longer writes `responded_by` (delivery and reconstruction); the prompt says `response`, `response_text` and `responded_at`. - The clear-resolved /ws trigger is the count only (no `cleared_by`). Tests: tests/unit/test_ent715_queue_person_fields.py (63). Mutations, each reverted from a scratch copy and red: the allowlist (42 red), the row filter and the item 404 (3 each), both write-back lines (1 each), the reserved prefix (2), the trigger (1), the prompt (1), and a new unclassified column (the person-side classification test, 6 red). One existing assertion flipped: test_ent611_native_ask.py (a file row's addressee is now withheld). Registered residuals: the answer/ending wakes still attribute the turn to the person (source_user_email on the execution row); REST row breadth for an admin-owned agent key stays with trinity-enterprise#719. Fixes Abilityai/trinity-enterprise#715 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… read rule (Abilityai/trinity-enterprise#715) The ent#499 problem report's "the agent never sees the words" now holds through the agent's own key too (workspace.md, core-agent.md). /cso --diff: no findings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…is reserved (Abilityai/trinity-enterprise#715) /review I1 on #3090. `_ABOUT_A_PERSON_ID_PREFIXES` said it was a subset of `_RESERVED_ID_PREFIXES`, and nothing checked that. The machine reads key on the first tuple; the file write-back, the resume wake and the ended-asks line key on the second. A heads-up prefix outside the reserved set would be hidden from a machine's read yet still written into the agent's file. Mutation: a third, unreserved prefix on the tuple turns exactly this test red (1 failed, 63 passed); the emitter-driven tests stay green, which is the gap. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Agent, system and other machine keys could read the email of the person who answered an ask, and of the person it was for, from the operator queue's reads. The file write-back also put the answerer's email into the agent's own
~/.trinity/operator-queue.json. This PR closes both paths.GET /api/operator-queue,/{id}and/agents/{name}give every non-person principal_MACHINE_ROW_FIELDS. That excludesresponded_by_id,responded_by_email,addressed_to_email(file rows too),disposed_by_emailandresolved_to. A column added later stays out until someone classifies it. A person (a JWT session, or the person's own user-scoped key:is_person_principal) still reads the whole row, so the web UI is unchanged.portal-inbox-collision-joins the reserved prefixes, so that alert also stays out of the agent's file, its resume turn and the Execution Context "Ended asks" line.responded_byon delivery or reconstruction. The prompt now saysresponse,response_textandresponded_at. Entries written before keep their old value./wstrigger is the count only.cleared_byis gone: a fleet-level trigger reaches every connection, and any key can mint a ticket.Changes
src/backend/routers/operator_queue.py:_MACHINE_ROW_FIELDS+_for_principal(allowlist, rows-about-a-person skipped), the item-route 404, the/wspayloadsrc/backend/services/operator_queue_service.py:is_about_a_person, the reservedportal-inbox-collision-prefix, the two write-back linessrc/backend/services/platform_prompt_service.py+config/trinity-meta-prompt/prompt.md: one sentencesrc/backend/client_portal/service.py: docstring (the residual it stated is closed)src/mcp-server/src/types.ts: comment only; MCP tools pass the narrower response throughoperating-room.md,requirements/security.md,requirements/core-agent.md,architecture/{api-endpoints,database,workspace}.md,docs/requirements/OPERATOR_QUEUE_OPERATING_ROOM.md(also removes an internal address from an example payload), a learnings fragment, anddocs/security-reports/cso-diff-2026-09-29-ent715-queue-person-fields.{md,json}No DB migration, no dependency, Docker or CI change.
Test Plan
cd tests && pytest unit/test_ent715_queue_person_fields.py -v. 63 passed. It pins the machine key set as a literal across seven machine principals plus one real minted agent key; the person side doubles as the classification guard. It also drives both platform emitters for real, runs the write-back through the bug(operator-queue): a pending approval can sit unseen for days — the human's card goes stale while the container↔platform sync stays silent #2915 harness, and pins the/wspayload and the composed prompt.test_ent611_native_ask.py, where a file row's addressee is now withheld). Full unit suite on the branch merged withdev: 19049 passed, 0 failed./verify-local --skip-agent --skip-unit: backend image build + import smoke, isolated boot + health, and integration (70 passed) are green. Its sequential unit stage fails 40 tests intest_ent666_objective_join.py,test_ent477_*andtest_retention_floor.py. That exact set also fails on the base commite87163125: order-dependent pollution that predates this change, not a regression. Every one passes on its own and under-n auto./cso --diff: no findings at the 8/10 gate.responded_by_email, and both platform alerts are listed.[]; 0example.comhits (3 in the JWT view).GET /api/operator-queue/{alert_id}: agent key 404 (the same body as a nonexistent id), JWT 200./wson Clear All:{"type":"operator_queue_cleared","data":{"scope":"resolved","count":72}}, nocleared_by.Not in this PR (registered)
source_user_email), and the executions API returns that field to keys. This is the platform-wide "who triggered this turn" attribution, out of scope by ruling and registered as debt.notifications_cleared.cleared_bycarries the same/wspattern in another router; registered as debt.Fixes abilityai/trinity-enterprise#715
🤖 Generated with Claude Code