Concepts

The ideas behind GridWeave, in the order you meet them: who may do what, how a device joins, how work reaches it and how it is checked.

Pre-release documentation.

Commands may change. The binaries are named gridweaved, gridweave, gridweave-admin and gridweave-agent. GridWeave is under construction and not released: there is no download, no installer package and nothing is code-signed.

Tenants and access

Tenants

A tenant is one customer or organisation inside an installation. Every tenant-scoped table carries a tenant id and PostgreSQL row-level security, so the database itself, not only the application code, keeps tenants apart; tests prove that a cross-tenant read returns nothing. A request names its tenant by the path prefix /t/{slug}/, and without one it goes to the tenant default that the first gridweave-admin bootstrap creates. Another tenant's resource is answered "not found", never "forbidden". Create a tenant with gridweave-admin tenant create --slug S --name N. Custom host names per tenant are not built.

Above the tenants sits the platform scope: installation-wide operations such as creating a tenant. Platform bindings and tenant bindings are kept apart, so a tenant administrator holds nothing at platform scope.

Device groups

A device group is a named set of devices, and groups can have parents. A role bound to a group applies to the devices in it and to its descendants. Enrolment tokens are created on a group, so a new device lands in the group whose token it used. A group can also carry a flag that asks for its sessions to be recorded (see recordings). Device groups are the usual place to bind roles, in the console under Device groups.

Roles, bindings and delegation

A permission is a dotted name such as device.view. A role is a set of permissions. A binding gives a user or a user group a role at a scope (platform, tenant, device group or device) with an effect of allow or deny. The effective set is the union of the allowed permissions minus the union of the denied ones, so deny always wins. Nothing is cached: a binding change applies to the next request.

Built-in roles include platform-admin, tenant-admin, device-admin, group-admin, user-manager, auditor, operator, helpdesk, viewer and member (every user has it). The tenant-admin role holds tenant-level permissions only and has no device access; device access comes from device-admin or group-admin.

Delegation stops anyone granting more than they hold:

  • An allow binding needs every permission of the role held by the person granting it, at that scope. A deny binding does not.
  • Nobody can change their own access, directly or through a group they belong to.
  • Removing a deny binding needs the binding permission at its scope, so an ordinary member manager cannot lift a restriction.
  • Acting on an account (edit, disable, reset the password, end sessions) needs every permission that account holds.
  • Adding a member to a group is a grant, and is checked as one.

Not built: realms, service accounts as subjects, and the import of rights from an earlier product.

Devices, enrolment and updates

Enrolment

An agent joins a tenant with four things: the server's agent address (port 8443 by default), the tenant slug, the installation's root certificate with its SHA-256 fingerprint (the pin), and a single-use enrolment token made on a device group (a number of uses and a validity in hours). The agent pins the root, so it trusts only that root even if the certificate file is swapped. It presents the token once, receives a per-device certificate for mutual TLS, and renews that certificate over its control stream. The token is read from an environment variable or a file, never from the command line, and is not written to any file or log by the agent. A used, expired or unknown token is refused with one and the same message, TOKEN_INVALID.

Revoking a device closes its live connection. Address allow and deny lists, flood, flap and clone detection protect the listener. The steps are in Deployment.

Updates and staged rollouts

An administrator imports a signed release (gridweave-admin releases import) and creates a rollout for it: a scope (the tenant, or device groups), one to ten cumulative rings that end at 100 percent, an optional weekly window with a time zone, a concurrency limit (50 by default), a minimum version and a health gate. A device’s place in the rings is a stable hash of its id, so a ring only grows. Update policies per device group and per device can switch updates off, pin a version or move a canary group into an early ring. The server answers an agent’s check with a version and a reason code, never with an address.

The agent updates itself. An installed agent asks the server on its own, downloads the manifest and artifact from the server it enrolled with, and verifies the signed manifest, the pinned keys, the size and the SHA-256 before it swaps its binary. If the new build does not stay connected within its time window, the previous build is restored, either by the new build itself or by a watchdog that the previous binary arms before the swap. The outcome is reported and audited. If the share of failed or rolled-back devices in a ring passes the gate (more than 2 percent by default, with at least one failure), the rollout halts and offers nothing until a person resumes or aborts it.

Status: built and proven on Linux under systemd (Ubuntu 24.04 ARM64), and on macOS only through a staged install root. Not verified: the macOS launchd restart and watchdog, anything on Windows (nothing swaps a binary there), x86-64, and rollouts to more than a handful of devices. Not built: an immediate “update now” (nothing is pushed), enrolment links and an install page. The keys in the repository are development keys and nothing is code-signed.

Signed commands

The server never tells an agent what to do on its own word. Every command arrives in an envelope that the server signed, which names the tenant, the device, the acting user, a two-minute validity window and the permissions the server found that user to hold. The signing certificate is short-lived and comes from a dedicated Command CA below the root the agent pinned at enrolment. Device and server certificates cannot sign commands, and neither can an agent gateway.

The agent verifies the envelope itself: the certificate chain, the signature, the device, the tenant, the time, replay, and that the permissions cover the action. It refuses anything that does not check out and answers REFUSED with a short reason. The audit entry is written in the same transaction as the job, before the first byte is sent. No message of the agent protocol carries code for the agent to run: the one text-for-an-interpreter field is an operator's script inside a verified envelope. Updates work the same way: the agent verifies a signed manifest and the artifact against keys compiled into it. Twenty-five forgery tests exercise the agent's verifier.

Running things

Jobs

A job runs one script on up to 500 devices. The request chooses an interpreter (sh, powershell or cmd), whom to run as (agent, the logged-in user or user_first) and a timeout. The server creates the job with one result row per device, signs one command per device and routes it over the message bus to the gateway holding that device's connection. With no connection the answer is agent_not_connected within two seconds. Each device reports a status, an exit code and its output, and the job moves from queued to a final state you read with GET /api/v1/jobs/{id}, in the console or with gridweave run. The script text, the interpreter and the run-as setting are in the audit entry.

The same signed-command mechanism carries power actions, notify, wake, process and service control, clipboard and open-URL. By default a script runs as the agent itself: the user who started it, or root when the agent runs as a service.

Sessions, consent, recordings and guests

Sessions

A terminal or files session is a live connection between a client and a device, joined by the relay. Opening one needs device.view plus device.terminal or device.files. The server signs an offer to the agent and a single-use grant for each leg; the agent verifies both itself, then connects out to the relay. The relay throttles a fast writer with credit-based flow control, and it closes a session within two seconds of a revoked permission. Limits per tenant include the number of sessions, an idle timeout (900 seconds by default) and a maximum duration (28,800 seconds by default). The web application's Terminal and Files tabs and gridweave shell and gridweave cp are the clients. Remote desktop is not built.

The grant carries a consent policy: none starts the session, notify tells the person at the device and starts, and prompt asks and starts only on a yes. The client sees that it is waiting, then that the session started or was denied. Until it starts, the client's input is dropped. On Windows the console user would get a Yes/No box; on Linux and macOS a helper application would show the prompt, but no such helper exists yet. With nobody to ask, the agent's headless_consent setting decides, and the default is to refuse. The Windows prompt was never compiled or run.

Recordings

The relay can record a terminal session into the tenant's part of object storage. Whether it does depends on the tenant setting recording.mode (off, selected by default, or all), the device group flag, the user, and an operator's explicit request. A recording is written in chunks with a hash chain and a manifest, and the web application has a player. A recording fails closed by default: if it cannot be stored, the session is refused or ended (recording.on_failure can be set to continue). Recordings are limited by size (256 MiB by default), count and retention.

Status: built for terminal sessions only, proven with fake agent legs, the real relay and a real S3 service. Not proven with a real agent or a browser. The agent shows no notice that a session is recorded yet, so the device user is told only by the consent policy. Desktop recording is not built. A recording is verified when it is read: the manifest and every chunk are checked against the values the database holds, and there are no signed download addresses. Object lock is not used.

Guest sharing

A person without an account can join one terminal session on one device through a link. The creator needs the share permission and the protocol’s permission, and a share can never give a guest more than its creator holds. The token is 256 random bits shown once, and only its SHA-256 is stored. The link carries the token in the URL fragment, and the guest page removes it from the address and spends a use only when the guest clicks Join. A share has a window (at least a minute, at most 168 hours by default), a limited number of uses and an optional view-only mode. Consent is at least notify, and the session is recorded under the same rules as any other. The share is checked against its creator’s current rights at every redemption and during the session, and revoking it closes both legs within milliseconds (10 ms was measured with the API and relay as separate nodes).

Status: built on the server and in the web application for terminal sessions, tried with fake agent legs and the real relay, never with a real agent or browser. The agent does not yet show the guest notice or enforce view-only from the grant; the relay does enforce view-only. Not built: recurring windows, port or web shares, agent-initiated shares.

Tokens and audit

Personal access tokens

A personal access token lets a person act on the API without a browser, and it is what gridweave uses. It starts with gwp_, is created under Account and is shown once; only its SHA-256 is stored. A token can never do more than its creator: it carries an optional list of permissions that must all be held by the creator, and on every request that list is intersected with the creator's current permissions. Remove a role and the token loses that access on the next request. Revoking, expiring or disabling the user takes effect on the next request as well.

Operations that only need a signed-in user, such as changing your own password, factors or sessions, are closed to tokens, as are creating another token and setting another account's password. A bearer request needs no anti-forgery header. Failures from one source network are throttled. At most 100 live tokens exist per user. Creation, use and denial are audited. Not built: administrators listing or revoking other people's tokens, resource-scoped tokens and service accounts.

Audit

Every state change, authentication event and permission denial writes one audit entry through a transactional outbox, in the same transaction as the change. The log is append-only and hash-chained per tenant, with one more chain for the installation. gridweave-admin audit verify checks every chain.

What this page does not cover

The product is under construction. Remote desktop, delivery of notifications (subscriptions are stored and nothing acts on them), passkeys, self-registration, reports and the bridge role are not built. The roadmap carries the full status, and security describes the model behind signed commands, grants and audit.