I’ve been taking a look at the AI integration options and the MCP server has been really useful, but it’s a bit scary that it has the full power of the user’s credentials. As AI is known to “go rogue” we’d like to limit the blast radius of such an event. Using Claude, I’ve been exploring such a control - and we’d like to contribute an option to create read-only auth tokens. The main use is reporting and integration accounts that only need to read tickets, assets and articles, without giving them a credential that can change data. The following has largely been crafted by Claude, overseen and tweaked by me, as it noted that the contribution instructions recommend asking here in rt-devel before crafting a PR.
Proposal (targeting 6.0-trunk):
- New column
AuthTokens.ReadOnly(default 0), set by a checkbox on the Create form. It can’t be changed afterwards (no write access,SetReadOnlydenied, likeSetOwner). UserForAuthStringrecords the token on the returnedRT::CurrentUser. Because the web UI acceptsAuthorization: tokenand opens a full session, we’d enforce read-only in the core rather than in REST2 alone, so REST2, REST 1.0 and token-started web sessions all behave the same.- Rights: for a read-only session,
RT::Principal::HasRight/HasRightsonly grant rights namedSee*/Show*(minusShowSearchBulkUpdate) plusLoadSavedSearch. The filter sits outside$_ACL_CACHE, so the same user’s normal sessions aren’t affected. - Writes:
RT::Record::Create,Deleteand__Setrefuse when the record’s CurrentUser is a read-only token session. This catches writes that don’t go through a rights check, such asRecentlyViewedTickets. System-user writes are unaffected.
Questions for the core team:
- Is enforcing at the model layer acceptable, or would you rather limit read-only tokens to REST2 and refuse them for web login?
- Is a naming-convention rule (
See*/Show*) the right way to decide read rights, or would you prefer an explicit list, or a flag onAddRight? RT::Shortenerrows are created when a web search runs. Should Shortener be exempt from the write guard as a cache, or should it fail and fall back to unshortened URLs?- Method names on
RT::CurrentUser:RT::Useralready has anAuthTokencolumn, so we’d avoid that name. Any preference? - Is branching 6.0-trunk with the upgrade step in
etc/upgrade/6.0.4, OK?
We’ll include API, REST2 and web tests, plus POD and UPGRADING notes.
If this looks like a useful addition, I’d appreciate guidance on the questions above and then I can get on and create the PR.
Many thanks,
Simon.