Not every operation is a query. Starting a service, stopping a Concurrent Manager, resetting a stuck Workflow Mailer — these are control-plane actions, and they run through two different transports depending on what kind of action it is.
Every EBS control action reaches your servers through the same outbound agent protocol described in Connectivity & Agent Protocol — no exceptions, no separate channel. What differs is which agent receives the command and how it's addressed:
| Op type | Examples | Routes to |
|---|---|---|
| Shell ops | Service status, Concurrent Manager start/stop, Apache/OHS, Node Manager | The app-tier agent directly, via /api/ebs-ctrl — a shell command runs locally under the applmgr user. |
| SQL ops | Running/failed concurrent requests, WF Mailer status and reset, OPP queue | The paired DB-tier connection — resolved from the app-tier connection first, then run as the APPS schema. |
| ADOP phase execution | Validate, Prepare, Apply, Actualize, Finalize, Cutover, Cleanup, FS Clone, Abort | The app-tier agent directly, via /api/ebs-ops/middleware-run — same shell-op transport as service start/stop, using the stored APPS password (SYSTEM/WebLogic when configured). |
An EBS environment usually has two TuneVault connections: one pointed at the application tier, one at the database tier. A SQL op initiated from the app-tier connection's dashboard needs to actually run against the database — so it has to find its sibling connection first.
The pairing key is ebs_instance_name — both connections for one EBS environment are tagged with the same instance name when they're set up, and this is what lets TuneVault know "these two connections are the same environment." If no paired DB-tier connection exists, the SQL op has nowhere to run and fails cleanly rather than guessing at a target.
Starting or stopping a service isn't a read — it changes something running in production. Every destructive shell op requires a client-side CONFIRM step before the command is even sent to the agent. This isn't just a UI nicety: it means a single accidental click on the wrong button can't bounce a service, because the request never leaves the browser without the second, explicit confirmation.
Oracle's Online Patching (ADOP) puts EBS into a distinct, sensitive state — patch edition switching, database DDL, and service restarts already in flight elsewhere. Bouncing a service or running certain SQL ops mid-cycle can corrupt the patch. TuneVault tracks this per connection:
adop_* phases are explicitly exempt from it; they are the patch cycle, so gating them on "a patch cycle is active" would refuse the very ops the gate exists to protect.
When ebs_adop_state.patching is true for a connection, destructive ops are refused server-side on both transports. On the shell path that means Concurrent Manager start/stop, Apache/OHS, OPMN, Apps Listener, Node Manager, WLS Admin, managed servers, WF Mailer, and Stop/Start All; on the database path it means session kills, instance shutdown/startup, PDB close, cache flushes, and stats gathers. The refusal happens in /api/ebs-ops/middleware-run and /api/db-ops/run before the command is ever queued for the agent, so it holds regardless of what the browser sends. Read-only ops are deliberately unaffected — status checks, ETCC runs, and every diagnostic query pass straight through, because seeing what the environment is doing mid-patch is exactly when you need it most. The dashboard shows a banner naming the current ADOP phase, and the gate lifts automatically the moment the detector observes the cycle has ended.
The rolling bounce is covered too, and refuses before its progress stream opens rather than failing halfway through — walking managed servers down one by one against a moving patch edition is the exact shape of the accident this prevents.
Every path decides the same way: each op carries a destructive flag on its catalog entry, and the gate reads that flag. It is not a list of op names kept somewhere else — a list drifts from the ops it names, and this one did.
It's a speed bump, not a locked door — and on the database side that matters more than it might look. Killing a session is exactly the tool you need when a session is blocking a hung ADOP worker, so refusing it outright would push you to sqlplus at the worst possible moment. An operator who genuinely needs a destructive op mid-cycle can re-send the request with the active ADOP session ID as adop_session_id. Requiring the session ID is the point: you can't clear the gate from muscle memory, you have to go and look at the patch cycle you're about to interfere with.
When a phase goes wrong, the guided execution flow is not the only path. ADOP Phase Status and ADOP Cutover Rollback remain valid DBA reference documentation for troubleshooting a stuck phase — they're for when something needs manual recovery outside the guided flow, at the sqlplus and adop command line.