WIP: fix(auth): a refused person reads what happened and what to do #60

Draft
james.maes wants to merge 1 commits from fix/plain-permission-messages into main
pull from: fix/plain-permission-messages
Owner

Draft: wording only, for review. Not for release this week; no version, release branch or installer file is touched.

What

A person the server refuses reads what happened and what to do, without a framework's name.

Before After When
The current QQQ user is not permitted to perform this operation. You are signed in, but your account is not allowed to use printing. Ask an administrator to give your account access to printing. 403 on a request that rests on the account alone: the identity read after sign-in (session without print station proof), operator/printers, admin/....
(same) You are signed in, but your account is not allowed to set up this print station. Ask an administrator to give your account permission to set up print stations, or to set this one up for you. 403 on devices/enroll.
(same) You are signed in, but your account or this print station is no longer allowed to print. Ask an administrator to check your account's printing access and this print station's access. 403 on a request that carries this print station's proof: device/..., device/bind, session with proof.
Sign in to QQQ to continue. Sign in to continue. 401, or no session.

A client edition that names its server (serverName in the edition file) has that name in the sentences: "You are signed in to Acme Cloud, but ...", "Sign in to Acme Cloud to continue." The generic build, and an edition that keeps the default, name none. The client reads no branding or product name from the server, so the edition is the only name it knows.

Why

A person refused by the print client read "The current QQQ user is not permitted ..." as a message from a different system and did not know what to ask for.

The server answers every refusal with the same 403 and the client does not read its body (unchanged), so the client cannot tell the reasons apart from the answer. It can tell them apart from what it asked, which is what the three sentences follow. The sentences name no role: which grant a print station needs is the server's rule and may change.

How it was tested

  • ./build/Verify.ps1 -ProtocolFixtures <fixtures of the protocol revision pinned in ci.yml, ac835f8>: locked restore, solution build with -warnaserror (0 warnings, 0 errors), Qqq.PrintAgent.Core.Tests 204 passed, Qqq.PrintAgent.Cli.Tests 377 passed. No signing, packaging or installer step was run.
  • A first run of the same script, made while another build was using the machine, had two Qqq.PrintAgent.Cli.Tests timeouts (AgentRuntimeQueuedJobsTests.QueuedJobAppearsAndCanBeCanceledBeforeAnyLocalReceipt, AgentControlConcurrencyTests.RemoteDisconnectAndReconnectDoNotInterruptBlockedPrintOrControlPolling); both pass on an idle machine and neither touches the changed code.
  • New and changed tests in QqqSessionAuthenticationTests: the sentence for each kind of refused request, with the server's body ignored; the refused identity read with and without print station proof; the edition's name used only when there is one; the existing 401/403 test now also asserts the two sentences.
  • Not tested: the installed companion and service on a real computer; nothing was printed.

Not changed here, and still naming the framework in text a person can reach: "The QQQ request did not succeed.", "QQQ authorization is required to restore the realtime connection.", "The printer is not exposed to QQQ on this computer.", "The job was not found or this QQQ server needs the printing operator-actions update.", the log lines, and the generic build's own name. They are not permission messages; say if they should follow.

Checklist

  • Commits are signed (no sign-off line, as the recent commits on main)
  • Zero build warnings
  • Tests added or updated
  • Docs updated for user-visible changes (CHANGELOG, Unreleased)

🤖 Generated with Claude Code

Draft: wording only, for review. Not for release this week; no version, release branch or installer file is touched. ## What A person the server refuses reads what happened and what to do, without a framework's name. | Before | After | When | | --- | --- | --- | | The current QQQ user is not permitted to perform this operation. | You are signed in, but your account is not allowed to use printing. Ask an administrator to give your account access to printing. | `403` on a request that rests on the account alone: the identity read after sign-in (`session` without print station proof), `operator/printers`, `admin/...`. | | (same) | You are signed in, but your account is not allowed to set up this print station. Ask an administrator to give your account permission to set up print stations, or to set this one up for you. | `403` on `devices/enroll`. | | (same) | You are signed in, but your account or this print station is no longer allowed to print. Ask an administrator to check your account's printing access and this print station's access. | `403` on a request that carries this print station's proof: `device/...`, `device/bind`, `session` with proof. | | Sign in to QQQ to continue. | Sign in to continue. | `401`, or no session. | A client edition that names its server (`serverName` in the edition file) has that name in the sentences: "You are signed in to Acme Cloud, but ...", "Sign in to Acme Cloud to continue." The generic build, and an edition that keeps the default, name none. The client reads no branding or product name from the server, so the edition is the only name it knows. ## Why A person refused by the print client read "The current QQQ user is not permitted ..." as a message from a different system and did not know what to ask for. The server answers every refusal with the same `403` and the client does not read its body (unchanged), so the client cannot tell the reasons apart from the answer. It can tell them apart from what it asked, which is what the three sentences follow. The sentences name no role: which grant a print station needs is the server's rule and may change. ## How it was tested - `./build/Verify.ps1 -ProtocolFixtures <fixtures of the protocol revision pinned in ci.yml, ac835f8>`: locked restore, solution build with `-warnaserror` (0 warnings, 0 errors), `Qqq.PrintAgent.Core.Tests` 204 passed, `Qqq.PrintAgent.Cli.Tests` 377 passed. No signing, packaging or installer step was run. - A first run of the same script, made while another build was using the machine, had two `Qqq.PrintAgent.Cli.Tests` timeouts (`AgentRuntimeQueuedJobsTests.QueuedJobAppearsAndCanBeCanceledBeforeAnyLocalReceipt`, `AgentControlConcurrencyTests.RemoteDisconnectAndReconnectDoNotInterruptBlockedPrintOrControlPolling`); both pass on an idle machine and neither touches the changed code. - New and changed tests in `QqqSessionAuthenticationTests`: the sentence for each kind of refused request, with the server's body ignored; the refused identity read with and without print station proof; the edition's name used only when there is one; the existing 401/403 test now also asserts the two sentences. - Not tested: the installed companion and service on a real computer; nothing was printed. Not changed here, and still naming the framework in text a person can reach: "The QQQ request did not succeed.", "QQQ authorization is required to restore the realtime connection.", "The printer is not exposed to QQQ on this computer.", "The job was not found or this QQQ server needs the printing operator-actions update.", the log lines, and the generic build's own name. They are not permission messages; say if they should follow. ## Checklist - [x] Commits are signed (no sign-off line, as the recent commits on `main`) - [x] Zero build warnings - [x] Tests added or updated - [x] Docs updated for user-visible changes (CHANGELOG, Unreleased) 🤖 Generated with [Claude Code](https://claude.com/claude-code)
james.maes added 1 commit 2026-11-13 14:23:18 +00:00
A person the server refused read "The current QQQ user is not permitted to
perform this operation" and took it for a message from another system. The
server answers every refusal with the same 403 and its body is not read, so
the sentence now follows what was asked: a request resting on the account
alone (including the identity read after sign-in), enrolling this computer,
or a request carrying this print station's proof. Each says the person is
signed in and what to ask an administrator for. "Sign in to QQQ to continue"
is "Sign in to continue".

A client edition that names its server has that name in the sentences; the
generic build names none. The failure kinds, the handling of 401 and 403
and every request are unchanged.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
You are not authorized to merge this pull request.
This pull request can be merged automatically.
This pull request is marked as a work in progress.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin fix/plain-permission-messages:fix/plain-permission-messages
git checkout fix/plain-permission-messages
Sign in to join this conversation.