priorauth.indocs

The gateway

Every call - from a console session, a platform agent, or an external partner over A2A - passes the same function in the same order. There is no second path, and no caller can skip a step by passing a flag.

#The checks, in order

  1. 1 · Registered tool
    A name not in the registry is refused. Nothing callable exists outside the registry, so an unregistered helper cannot be reached by an agent.
  2. 2 · Practice binding
    The principal must be bound to a practice, and practice_id comes from the principal - never from the arguments. A call whose arguments name a different practice is refused as cross_practice.
  3. 2b · Tenant lifecycle
    A provisioned-but-not-activated tenant, or a suspended one, cannot transact. A suspension has to stop agents at once, not at renewal.
  4. 2c · Channel authorisation
    A partner-scoped principal must name a practice, that practice must have authorised THAT channel, and the channel must be live. Evaluated per call, so suspending a channel stops every practice on it in the same instant.
  5. 3 · Atom check
    Server side, against the principal's role-derived atoms. A missing atom is a denial, not a filtered result.
  6. 3b · Agent control
    A paused or quarantined agent is refused here, before the autonomy maths, so an operator during an incident is told the lever was pulled rather than handed a permissions error.
  7. 4 · Autonomy mask
    The effective level is the strictest of four: the principal's own level, the practice ceiling, the external ceiling if the principal is external, and the agent type's eval-licensed ceiling. Below the tool's floor, the tool is unavailable rather than penalised.
  8. 5 · Budgets
    Two scopes, two windows. One runaway principal must not exhaust the practice, and one practice must not exhaust the platform.
  9. 6 · Chart-write consent
    Declared on the spec as requires_write_consent and checked once, centrally. A read connection is not consent to write.
  10. 7 · Execute, then audit
    The handler runs behind a circuit breaker. Output is tagged untrusted. An audit event carries the principal, the practice, the correlation id and the purpose of use.
Order is deliberate
A stopped agent is told it is stopped, not that it lacks a permission. During an incident the difference decides whether an engineer reads scopes for twenty minutes or looks at the lever somebody pulled.

#Denied is nonexistent

A denial is uniform and fails closed. Where a resource would leak its existence, the answer is a not-found shape rather than a forbidden one: a 403 confirms the thing is there and that somebody else can reach it, which is itself information.

#Async handlers produce async envelopes

Every tool was synchronous until the eligibility rail, which makes a network call. A promise handed back inside result does not fail - it reads as an object with no properties, so result.codes is undefined, an empty list looks like "nothing found", and the caller concludes the opposite of the truth.

This shipped once
The first version cleared a scheduled surgery that needed prior authorization, because an empty answer and a list of negatives are the same shape to a naive filter. A promise now never leaves the gateway inside an envelope: if the handler is async, the envelope is async, and a test asserts no registered tool returns a thenable.

#Output is untrusted

Everything a tool returns is tagged untrusted: true. It is data. Instructions inside it - in a payer note, an attachment, a fax transcription - are inert. See Untrusted content.