Skip to content
Version 1.0.0

Administration console

The console's 35 endpoints, the permission and role each one requires, its 11 environment variables, its tabs, and what the build profile removes from it.

Internal, subject to change without notice. This page describes the gateway’s administration surface. Unlike the Anthropic-compatible relay, it is not a contract: its paths, permission names and settings can change from one version to the next with no deprecation step. What is published here is published so an administrator can operate the version they installed, not so a program can build on it.

The console is the only place in the product where you declare a model provider, a model and an endpoint. Without those three declarations, an installed gateway answers 404 to everything.

Paths, permission names, role names and variable names are reproduced exactly as the code writes them. Translating them would make this page say something other than what the reader has in front of them.

The console depends on the profile it was built with. The profile is a build parameter, not a setting: an artifact does not know which one it carries and does not change it. The air-gapped profile is what you get without specifying anything, and it leaves out part of the surface: out of 35 endpoints, 15 are not mounted (they answer 404, not 403), and 4 of the 7 tabs are absent from the shipped bundle. A console with a single tab is not a misconfigured console.

Who gets in also depends on the profile. In the air-gapped profile, the console delegates authentication to the customer’s enterprise directory and checks no password: with no directory configured, nobody gets in. In the hosted profile, a shared username / password pair opens everything. That state is tolerated for a first start, and is removed once roles are assigned.

Every endpoint requires a named permission, and every permission is carried by a single role. Opening the console requires console:administrer-l-instance; reading the administration action log requires journal:lire, which belongs to the auditor, and a single subject cannot hold both administration and audit. So an instance administrator cannot read that log, including their own: a log the administrator can both read and write proves nothing. On a fresh instance, nobody holds the auditor role, so nobody reads that log.

There are 35, in the order the table declares them. The method is part of the identity of the power granted: GET /api/endpoints and DELETE /api/endpoints/:id are not the same right.

An endpoint absent from this table is refused, not open. 14 entries carry hosted profile only instead of a permission: the refusal is the same, the course of action is not. “No permission covers this path” is a gap to fill, “this path does not apply to this profile” is a decision.

MethodPathRequiresRole that carries itProfile that mounts it
GET/api/usersmembres:lire-l-instanceadministrateur-d-instanceserverless only
POST/api/usershosted profile onlynoneserverless only
POST/api/users/:id/rotate-keyhosted profile onlynoneserverless only
GET/api/users/:id/keyshosted profile onlynoneserverless only
POST/api/users/:id/keyshosted profile onlynoneserverless only
POST/api/users/:id/keys/:keyId/revokehosted profile onlynoneserverless only
DELETE/api/users/:idhosted profile onlynoneserverless only
PATCH/api/users/:idhosted profile onlynoneserverless only
GET/api/planshosted profile onlynoneserverless only
POST/api/planshosted profile onlynoneserverless only
PATCH/api/plans/:idhosted profile onlynoneserverless only
DELETE/api/plans/:idhosted profile onlynoneserverless only
GET/api/usagehosted profile onlynoneserverless only
GET/api/usage/filtershosted profile onlynoneserverless only
GET/api/spending-capshosted profile onlynoneserverless only
GET/api/providersfournisseurs:administreradministrateur-d-instanceboth
POST/api/providersfournisseurs:administreradministrateur-d-instanceboth
DELETE/api/providers/:idfournisseurs:administreradministrateur-d-instanceboth
GET/api/modelsmodeles:administreradministrateur-d-instanceboth
POST/api/modelsmodeles:administreradministrateur-d-instanceboth
DELETE/api/models/:idmodeles:administreradministrateur-d-instanceboth
GET/api/endpointsendpoints:administreradministrateur-d-instanceboth
POST/api/endpointsendpoints:administreradministrateur-d-instanceboth
PATCH/api/endpoints/:idendpoints:administreradministrateur-d-instanceboth
DELETE/api/endpoints/:idendpoints:administreradministrateur-d-instanceboth
POST/api/policiespolitique:administreradministrateur-d-instanceboth
GET/api/organizationpolitique-d-organisation:administreradministrateur-d-instanceboth
POST/api/organizationorganisations:administreradministrateur-d-instanceboth
POST/api/organization/policypolitique-d-organisation:administreradministrateur-d-instanceboth
GET/api/audit/organization-policypolitique-d-organisation:lireauditeurboth
GET/api/administration-actionsjournal:lireauditeurboth
GET/api/audit/agent-actsjournal:lireauditeurboth
POST/api/audit/agent-sessions/:session/revocationsessions:revoqueradministrateur-d-instanceboth
GET/api/agent-executionconsole:administrer-l-instanceadministrateur-d-instanceboth
GET/console:administrer-l-instanceadministrateur-d-instanceboth

An allowlist rather than a prefix: a prefix would let in anything someone might one day drop into the directory. These paths carry no deployment data, and the login page has to be able to display before you are logged in.

  • /favicon.svg
  • /client.css
  • /client.js
  • /fonts/:fichier

Air-gapped profile only. These paths are mounted ahead of the authentication middleware and grouped under a common prefix (/auth/) that the middleware lets through: the directory’s response arrives on a redirect URI which, by definition, is not yet authenticated.

MethodPath
GET/auth/login
GET/auth/callback
GET/auth/logout

An authentication refusal names the mechanism (this console delegates to the directory) and never the state of the deployment. The exact reason goes to the service logs. An unreachable directory answers 503, not 401: “I cannot verify” is not “you are not allowed”, and confusing the two would send an operator hunting for a permissions problem while their directory is down.

There are 11, read from the console container’s environment. The gateway container reads its own from its own: two containers, two environments, nothing shared to arbitrate.

VariableRequiredProfile where it has an effectEffect
ADMIN_USERyeshostedUsername of the shared administration pair. Read when the module loads: the process refuses to start if either of the two is missing, rather than opening a port that nothing guards. This pair names no subject, carries no role assignment and cannot be revoked: it is tolerated for a first start, and is removed once roles are in place. The code that reads it is absent from the artifact in the air-gapped profile.
ADMIN_PASSyeshostedPassword of the same pair, under the same conditions. In the air-gapped profile, the console checks no password: the variable has no reader there.
DATABASE_URLno, and that is the trapbothPostgreSQL connection string. Its absence does not make startup fail: the console falls back to a local development database whose credentials are written in the code, so a deployment that forgets the variable reports nothing: it connects elsewhere. The value of that fallback is not reproduced here. A sslmode parameter carried in the URL makes startup fail: validation of the database certificate is set by the code, it is not configured in the URL.
PORTnobothListening port of the console. Absent, 6002.
DATABASE_CA_CERT_PATHnobothPath to the certificate authority file to check the database certificate against. Absent, validation stays active using the system authorities. Set to an unreadable file, startup is refused: without that authority the connection would fail anyway, later and further from its cause. No effect on a local database.
DATABASE_CA_CERTnobothThe PEM content of the same authority, for platforms that can only pass environment variables and offer no disk to mount a file on. This is a second way into the same mechanism, not a second mechanism: a value that carries no certificate stops startup, and so does setting both variables together, because nothing would say which one is authoritative. An authority’s certificate is public: it is not a secret.
OIDC_ISSUERyesair-gappedExpected issuer of the enterprise directory, and root of its discovery. An absolute https: URL, with no query and no fragment; any other form is refused, including for a local address. Without it, no directory is configured and nobody gets in.
OIDC_CLIENT_IDyesair-gappedOAuth 2 client identifier of this deployment with the directory. Set without an issuer, or the other way round, the configuration is partly in place: the console starts and refuses everything.
OIDC_CLIENT_SECRETnoair-gappedConfidential client secret, to be set only if the directory requires it. The code exchange is protected without a shared secret; where the directory accepts a public client, not holding one is strictly better than holding one.
OIDC_AUDIENCEnoair-gappedExpected audience in the token. Absent, the client identifier serves as the audience.
OIDC_REDIRECT_URIyes as soon as a directory is configuredair-gappedReturn URI of the login flow. It is specific to this console and read from its container’s environment. Directory configured but URI absent: the console starts, to stay diagnosable, and refuses everything, announcing at startup what is missing.

There are 7, in display order. That order does not depend on the profile: the list is declared in full, including the entries the shipped bundle does not contain. The console opens on the first available tab.

RankLabelIdentifierProfile that serves it
1Usersusershosted only (absent from the bundle built in the air-gapped profile)
2Plansplanshosted only (absent from the bundle built in the air-gapped profile)
3Endpointsendpointsboth
4Usageusagehosted only (absent from the bundle built in the air-gapped profile)
5Capscapshosted only (absent from the bundle built in the air-gapped profile)
6Policygovernanceboth
7Auditauditboth

A tab absent from the bundle built in the air-gapped profile is not a hidden tab: neither its label, nor its forms, nor its calls are in the artifact.

Three of them touch the console. Each one is an entry point that the air-gapped profile embeds as is, and that the hosted profile replaces with another implementation. With no explicit profile, the build produces the air-gapped profile: an oversight can only yield the restricted artifact.

BoundaryWhat the air-gapped profile embedsWhat the hosted profile substitutes
authentificationgateway-admin/src/authentification/index.tsgateway-admin/src/authentification/local/index.ts
comptesgateway-admin/src/comptes/index.tsgateway-admin/src/comptes/present/index.ts
ongletsDeComptesgateway-admin/src/client/ongletsDeComptes/index.tsgateway-admin/src/client/ongletsDeComptes/present/index.ts

The meaning of each screen, the order of the commissioning steps, the form fields and their input checks, and the detail of refusals per endpoint (which case gives 400, 409 or 404). No declaration carries them: they live in conditions written throughout the code and in interface components with no manifest. Extracting them would mean analyzing arbitrary code, and a fragile extraction that publishes an incomplete list is worse than no list at all.

They are covered by guides, which are the page type made for them:

The full catalog of roles and their permissions, beyond those the console requires, belongs to the gateway reference.