https://<box>/_guard/admin, linked from the header of every guard page.
Administrators only; a read-only user who opens it sees “Only
administrators may open this page.”
The page is server-rendered and works without JavaScript. Every action on
it requires an administrator session and is checked for its Origin.
Environments
One row per <project>/<environment> the box serves: the bundle it is
running (main@1a2b3c4, with a wip tag when the bundle was packed from a
tree with uncommitted changes) and a link to the environment’s values
page. See Environments & values.
Users
Everyone who has ever signed in. Nobody is provisioned here — a person’s record is created at their first login, from your directory.
| Column | Meaning |
|---|---|
| User | Display name, with the address underneath; a you tag on yourself. |
| Role | admin or readonly. An override tag means an administrator pinned the role on this box; hovering shows what the directory says. |
| Status | active or disabled. |
| Last login | When they last signed in. |
The heading shows seats <used>/<total> in use — see
Seats.
Actions
- make admin / make readonly — pin a role on this box. The override wins over whatever the directory grants, survives re-login and the periodic re-check, and applies to the person’s live sessions immediately. Use it to fix a mapping now, without waiting for a change at your identity provider.
- clear override — hand the decision back to the directory.
- disable — shut the person out of this box without touching your
directory. Their live sessions end at once, and their next login is
refused (
login.refused, reason account disabled on this box). A disabled person does not hold a seat. - enable — undo a disable.
Role and status changes are recorded as role.changed and
user.status.changed.
Active sessions
Who is signed in right now: user, role, the environment they selected, and
when the session started. kill ends one session immediately
(session.revoked, reason ended by
Continuous integration
https://<box>/_guard/ci creates the GitHub App through which the box
reports checks on your pull requests and deployments. GitHub asks you to
confirm and sends you back; the box keeps the App’s key and the guard
keeps nothing. The App is asked for checks: write and pull requests:
read — it is never given access to your code. Creating the App is
recorded as ci.app.installed.
Install the App on the repositories the box should watch, from the App’s page on GitHub. How events map to environments is described in Pushing suites.
Notifications
https://<box>/_guard/notifications is where a project’s channels — Slack,
Telegram, a webhook — and the rules that send to them are managed: add,
edit, switch off, send a test event; mute a series or the project; set
quiet hours. Every change is recorded (notify.channel.*, notify.rule.*,
notify.test.sent, notify.mute.*, notify.series.reset,
notify.quiet-hours.*), never a secret. A readonly session sees the page
without its forms. What is announced, and when, is described in
Notifications.
The audit trail
The box writes an append-only JSONL file per UTC day, meant for your SIEM to collect. The guard never reads it back to make decisions. A write failure is logged and never turns into a refused login.
Recent audit on the Administration page shows the last 50 records as a table — when, event, user, client address, a one-line summary — with the raw JSON record folded under each row. If the box has no audit directory configured, the page says so and events go to the process log instead.
Every record carries kind and at; events that identify a person carry
user (issuer, subject, displayName, email), and events from a
browser carry ip.
kind | Meaning | Fields |
|---|---|---|
login.succeeded | A sign-in completed. | providerId, role, user, ip |
login.refused | A sign-in was refused: bad credentials, disabled account, no mapped group, unverified email, directory unreachable. | providerId, reason, user (when known), ip |
logout | The person signed out. | user, ip |
seat.denied | Refused because every licensed seat is held. | user, seats, seatsUsed, ip |
session.revoked | A session ended other than by logout: a directory re-check, an administrator’s kill, or a provider removed from the configuration. | user, reason |
role.changed | A live session’s role moved. | user, from, to |
user.status.changed | An administrator disabled or enabled someone. | user, status, by |
ci.app.installed | A GitHub App was created for this box — the moment it gains the ability to write checks on your repositories. | user, app, by |
env.value.set | An environment’s target, a variable or a secret was set from the values page. Name only, never the value. | user, environment, valueKind, name |
env.value.removed | The same, removed. | user, environment, valueKind, name |
secret.revealed | An administrator looked at a secret’s value — shown on the page (show) or copied to the clipboard (copy). One event per look. Names only. | user, environment, names, how, ip |
env.values.replaced | An environment’s layers were replaced as a whole from the JSON editor. Names by layer. | user, environment, set, removed |
environment is always <project>/<environment>. No event ever carries a
secret’s value.