Class Access

java.lang.Object
com.axelor.ai.governance.access.Access

public final class Access extends Object
What one AI call may do for its user: the one place the AI asks, so every path answers alike.

Three things decide, and each must allow: the platform's permissions, the permissions of every agent on the call's chain, and the restrictions in force — the last two read from AiRules. An access made for platform() has no agent and holds to the platform alone, for what a user configures rather than what an agent reads.

The platform's permission records decide, never view attributes. Model and record access are the platform's own (JpaSecurity), administrators exempt. Field access reads a field rule's canRead/canWrite flag as QueryAccessValidator does, with no administrator exemption; its hideIf/readonlyIf are view attributes and are not read. A custom field is readable unless it names roles the user lacks, and writable exactly when readable.

With no user nothing is permitted: an AI call always runs as someone. Nothing here catches a failure; a check that throws fails the call rather than letting it through or quietly refusing.

Built per call, so the answers it memoises cannot outlive a change to the user's rights.

  • Method Details

    • of

      public static Access of(AiAgent agent)
      What the agent may do for the current user, on the model it is served by.
    • of

      public static Access of(List<AiAgent> chain)
      What the last agent on the chain may do for the current user, a sub-agent held to the reach of every agent that consulted it, on the model the last one is served by. An empty chain, or a null on it, reaches nothing.
    • of

      public static Access of(List<AiAgent> chain, Destination destination)
      The same, with what the call reads going to destination.
    • ofPath

      public static Access ofPath(List<String> codes)
      What the agents on the path may do for the current user: their codes, from the root, as a request carries them, on the model the last one is served by. A code no agent has reaches nothing.
    • ofPath

      public static Access ofPath(List<String> codes, String chosen)
      The same, on the model the user chose for the turn when there is one.
      Parameters:
      chosen - the code of the model the request names, or null
    • ofRequest

      public static Access ofRequest(ChatRequest request)
      What a request's turn may do: its agents', on the model serving it.
    • platform

      public static Access platform()
      The current user's own access, with no agent: for what the user configures or sees in the application — a knowledge base they may use, a chat's subject in their list — never for what an agent reads.
    • forIndexing

      public static Access forIndexing(Destination destination)
      What may be sent to destination when nobody asks: a record knowledge source's text, sent to the embedding model when it is indexed. Only the global policies and those listing the destination apply — there is no agent to match the others — and only mayReceive(com.axelor.ai.governance.access.ModelRef, java.lang.String) answers.
    • read

      public void read(ModelRef model, String field)
      Notes that a field's value is handed to the model. A chat keeps what entered it, and every later call in it sends that again: each must be allowed to receive it (mayReceive(com.axelor.ai.governance.access.ModelRef, java.lang.String)).
    • readPath

      public void readPath(Class<? extends Model> entity, String path)
      Notes every field along a dotted path on an entity: each one's value is handed over.
    • destination

      public Destination destination()
      Where this access sends what it reads: the model it is for, and its provider.
    • rulesStamp

      public static List<Long> rulesStamp()
      What the agents' permissions and the restrictions in force were read from: equal while none changed, so a caller that checked once may skip asking again.
    • receivableRows

      public Filter receivableRows(ModelRef model)
      The rows whose values may go to this access's destination, by the restrictions' conditions alone; null when no condition limits them. For an indexing access, a condition that needs a user to evaluate covers every row.
    • mayReceivePath

      public boolean mayReceivePath(Class<? extends Model> entity, String path)
      mayReceive(com.axelor.ai.governance.access.ModelRef, java.lang.String) for every field along a dotted path on an entity.
    • reads

      public Set<Access.Read> reads()
      The fields whose values the call handed over.
    • mayReceive

      public boolean mayReceive(ModelRef model, String field)
      Whether the field's value may go to this access's destination for its agents, by their permissions and the restrictions alone, not the user's own permissions: for data already in a chat, which another member's turn may send on.
    • user

      public User user()
      The user the call runs as, or null when there is none and nothing is permitted.
    • modelDenial

      public String modelDenial(ModelRef model, Operation operation)
      The refusal for operation on the model as a whole, or null when it is permitted.
    • record

      public RecordAccess record(ModelRef model, Operation operation, Long id)
      Whether operation is permitted on one record, which the caller has found: an unconditional permission grants any id, one that names no record included.

      The model check does not answer this: a permission whose access is conditional passes it, deciding row by row being what the condition is for. A record the user cannot even read is RecordAccess.INVISIBLE rather than denied, so it is reported as an ID that does not exist would be: a denial would confirm that this one does.

    • recordsDenial

      public String recordsDenial(ModelRef model, Operation operation, Collection<Long> ids)
      The refusal for the operation on records record(com.axelor.ai.governance.access.ModelRef, com.axelor.ai.governance.access.Operation, java.lang.Long) did not grant it on: the user's, when their own permissions refuse it on any of them, else the assistant's.
    • readable

      public Set<Long> readable(ModelRef model, Collection<Long> ids)
      The records among ids the user may read, as record(com.axelor.ai.governance.access.ModelRef, com.axelor.ai.governance.access.Operation, java.lang.Long) decides for each, in one query: for a page of related records, where a query each would be one per record.
    • rowFilter

      public Filter rowFilter(ModelRef model)
      The row-level read filter for the model, for a tool to combine with its own query: null when no row is excluded. With no user, every row is.
    • canRead

      public boolean canRead(ModelRef model, String field)
      Whether the call may read a field: a property, a custom field, or a custom model's field.
    • canWrite

      public boolean canWrite(ModelRef model, String field)
      Whether the call may write a field, to create or to update.
    • refuser

      public Access.Refuser refuser(ModelRef model, String field, boolean write)
      Who refuses the call reading or writing a field, or null when nobody does: the user's own permissions, so a refusal says they may not, or only the AI's, so it says the assistant may not.
    • pathDenial

      public String pathDenial(Class<? extends Model> entity, String path)
      The refusal for reading a dotted path on an entity, or null when every field along it, and every model it enters, may be read. A custom field ends a path.

      A copy of QueryAccessValidator.checkFieldRead's walk, answering instead of throwing; unify the two once this API is stable.

    • queryAccess

      public QueryAccess queryAccess()
      The query engine's view of this access: the platform's checks, and the AI layer's on every model, field and row a query reads.