The juudd panel does not deploy anything, publish anything or run any SQL. It does the things that have to be done by a person, and everything else happens in the conversation with your assistant.
That is a rule with two clauses, and the second one has moved real behaviour. This post is the rule, the case that nearly broke it, and one change it caused to a tool that was already shipped.
The panel started out unable to do anything
The first panel was read-only on purpose. Its source said so: nothing here deploys, deletes or runs SQL, because the work happens in the conversation, and a panel with buttons for the same operations would be a second way to do everything, drifting from the first.
That argument was right about the thing it was aimed at. It was being read as something bigger, an argument for a panel that could do nothing at all. Then the owner asked for subscription management, a way to hand a database over, the activity log and a place to see a site's own addresses. Two of those were reads. The other two were not, and refusing them on the strength of an old paragraph would have been applying a rule past the case it was written for.
The line
A panel action is allowed when no tool does the same job, or when it is an act a person should be holding rather than a model.
Everything else stays in the conversation. Deploying, publishing, running SQL and rebinding a credential all have tools, an assistant does each of them better than a form could, and none of them is on the panel. You can check that against the code: the panel's account routes list a session, sites, activity, refusals, billing, a database credential, a hand-over, secrets and reports, and none of them deploys or publishes.
| the action | a tool does the same job? | allowed by |
|---|---|---|
| Subscription | no | the first clause: nothing else does it, so the panel is not a second way |
| Activity log | no, it is derived from the store | the first clause, and it was always a read |
| A site's addresses | list_deploys reads the same records | a read is not a second way to act |
| Hand-over of a database | transfer_database | the second clause |
Why the exit has a door in both places
Hand-over is the interesting row, because a tool already does it. Look at what the tool really does: transfer_database does not move anything. It mints a one-time link and records that a hand-over was issued. The transfer happens when a person opens that link, outside our system, and nothing reports back when they do.
So the panel route and the tool are not two ways to perform an act. They are two ways to ask for the same link, and the act itself was always a person's.
Given that, the only question is whether the link should need an assistant in the loop. It should not. The promise on the site is a one-call exit with no deadline, and an exit that only opens from inside a conversation needs a working assistant, a connected account and a model willing to call the tool.
A customer who wants their data out at the moment they are least happy with us is exactly the customer who should not need our good behaviour to get it.
Both doors record what they did, through the same recorder under the same account, and both mint the link without claiming the database moved. The panel route has a test asserting its reply makes no such claim.
The second clause has changed a shipped tool
create_database used to hand the owner connection string to the assistant. That put a live credential into a tool result, which is to say into a model's context, into whatever transcript the client keeps, and into every log on the way. The tool's own description spent two sentences apologising for it, with warnings aimed at a person while the payload went to a model.
Only someone at a terminal ever needed that string. The assistant did not: apply_sql already runs against the database, and the site's functions get a separate restricted role automatically. So the string moved. Today create_database says in its description that it does not return a connection string, and its reply says where a person can read it, in the panel. The panel's route for it is a POST and not a GET, so it is recorded, and so a secret is not in a URL that a browser keeps in its history.
The same reasoning puts the value of a site's secret on the panel. The assistant declares the name, and the person pastes the value in over a session they signed in for.
What the panel does not try to be
It is not a place to manage a site. Deploys, versions, stopping and republishing all stay in the conversation, because a form for them would compete with the one thing this product is, which is the tool list.
It does not take a card. Plan changes go to a hosted page at the billing provider, and the panel's whole billing interface is a button that opens it. Rebuilding payment entry here would put this code in the path of a card number to gain nothing.
The first clause is not a promise it will stay small. It says only which things are allowed, and each new action has to be argued against the same two sentences.
The rule, once
Put an action on the panel only if no tool does the job, or if it is an act a person should be holding rather than a model; everything else stays in the conversation. The tools and their limits are listed in the docs.