> For the complete documentation index, see [llms.txt](https://gabriel-j-shapiro.gitbook.io/metalex-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://gabriel-j-shapiro.gitbook.io/metalex-docs/protocol-reference/access-control.md).

# Access control (BorgAuth)

All access control in the protocol runs through **BorgAuth** — a single ACL contract per cyberCORP. BorgAuth uses **numeric role levels in a hierarchy**, not named roles.

* **Source:** [`src/libs/auth.sol`](https://github.com/MetaLex-Tech/cybercorps-contracts/blob/develop/src/libs/auth.sol)

## The role model

A role is a `uint256`. Higher numbers outrank lower ones. `onlyRole(role)` **passes when `userRoles[user] >= role`** — it is a threshold check, not an exact match.

### Built-in role constants

| Constant          | Value |
| ----------------- | ----- |
| `OWNER_ROLE`      | `99`  |
| `ADMIN_ROLE`      | `98`  |
| `PRIVILEGED_ROLE` | `97`  |

### Roles the protocol assigns

The `CyberCorpFactory` and `CyberCorp` set these levels when a cyberCORP is deployed:

| Holder                                           | Level               | Why                                                                                               |
| ------------------------------------------------ | ------------------- | ------------------------------------------------------------------------------------------------- |
| Company officer (`CompanyOfficer.eoa`)           | `200`               | Set by `CyberCorp.addOfficer` / by the factory. `200 ≥ 99`, so officers also satisfy `onlyOwner`. |
| `CyberCorp` contract                             | `200`               | So the corp can act on its own auth.                                                              |
| `IssuanceManager`, `DealManager`, `RoundManager` | `99` (`OWNER_ROLE`) | So the manager contracts can call owner-gated functions on the suite.                             |

> There are **no named roles** such as `ISSUER_AUTHORITY` or `OFFICER_AUTHORITY`. Authority is the numeric level a contract requires at a given function. Officer = `200` is the level a human officer holds.

## BorgAuth functions

```solidity
uint256 public constant OWNER_ROLE = 99;
uint256 public constant ADMIN_ROLE = 98;
uint256 public constant PRIVILEGED_ROLE = 97;

mapping(address => uint256) public userRoles;
mapping(uint256 => address) public roleAdapters;

function updateRole(address user, uint256 role) external;       // caller must hold OWNER_ROLE
function initTransferOwnership(address newOwner) external;      // caller must hold OWNER_ROLE
function acceptOwnership() external;                            // caller must be pendingOwner
function zeroOwner() external;                                  // caller renounces to role 0
function setRoleAdapter(uint256 role, address adapter) external;// caller must hold OWNER_ROLE
function onlyRole(uint256 role, address user) public view;      // reverts if under-authorised
function matchRole(uint256 role, address user) public view;     // reverts unless exactly equal
```

* **`updateRole`** — the single grant/revoke entry point. Set a user's level up or down. Requires `OWNER_ROLE`.
* **`zeroOwner`** — the owner renounces itself to level `0`, permanently removing admin control from contracts using this auth.
* **Role adapters** — `setRoleAdapter` plugs in an `IAuthAdapter` so a role can be satisfied by custom logic (e.g. a credential check) instead of, or in addition to, a stored level.
* Ownership transfer is two-step: `initTransferOwnership` then `acceptOwnership`.

## Using BorgAuth in a contract: `BorgAuthACL`

Protocol contracts inherit `BorgAuthACL`, which holds the `AUTH` reference and provides modifiers:

| Modifier       | Passes when the caller's level is… |
| -------------- | ---------------------------------- |
| `onlyOwner`    | `≥ OWNER_ROLE` (99)                |
| `onlyAdmin`    | `≥ ADMIN_ROLE` (98)                |
| `onlyPriv`     | `≥ PRIVILEGED_ROLE` (97)           |
| `onlyRole(n)`  | `≥ n`                              |
| `matchRole(n)` | exactly `n`                        |

Example: `CyberCorp.addEscrowedOfficerSignature` is `onlyRole(200)` — only an officer (level 200) can call it; most other `CyberCorp` functions are `onlyOwner` (level ≥ 99).

## A note on `onlyIssuanceManager`

`CyberScrip`, `CyberCertPrinter`, and `CyberShares` gate their mutating functions with `onlyIssuanceManager` — a check that `msg.sender` *is* the IssuanceManager contract, **not** a BorgAuth role check. End users act through the IssuanceManager, which itself is authorised via BorgAuth.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://gabriel-j-shapiro.gitbook.io/metalex-docs/protocol-reference/access-control.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
