Delegation commands¶
Commands that delegate access and run a program under a grant. Global flags are in the CLI hub.
gdsgate delegations create --can <cap>... [--ttl <secs>] [--bind-key <dir> | --exec <prog> [-- <args>...]]¶
Delegates a subset of your own access as a grant. Each
--can is a capability <lane>:<verb>@<resource> (db:read@prod-pg,
ssh:connect@bastion, kube:read@staging, mcp:search@corp,
llm:call@models-prod, web:read@grafana); repeat it to grant several.
An MCP capability may name one of a server's three data paths:
mcp:tool:<name>@<server> (the default, so mcp:<name>@<server> is the same),
mcp:resource:<name>@<server> and mcp:prompt:<name>@<server>. A resource is
named as the server's resources/list names it; its URI is not accepted.
The ssh lane takes three verbs: ssh:connect@<host> is the session,
ssh:forward@<host> is ssh -L and ssh -R, ssh:agent@<host> is ssh -A.
Only connect opens a session, and none implies another; see
what a grant carries into an ssh session.
The web lane takes read, write and tunnel. web:tunnel@<resource> covers a
channel the gateway carries without reading it: a WebSocket upgrade into an
application, or CONNECT through a web-egress resource whose backend has
inspect unset or false (see
Configuration → Reading what a way out carries).
web:write does not include web:tunnel: grant web:tunnel for https through
such a resource. A web-egress resource with inspect = true opens no channel;
https through it is web:read / web:write by method, as for plain http.
The gateway refuses any capability your own policy would deny. Prints the grant id.
| Flag | Default | Purpose |
|---|---|---|
--can <cap> |
from --profile; otherwise required |
Capability to delegate. Repeatable. Required, except with --profile, --list-profiles or --list-agent-profiles. |
--profile <name> |
not set | Take the rest of the flags from a saved delegation ([[delegation_profiles]]). Any flag given alongside wins over the row's value for it; --can and --sandbox-allow replace the row's list; they do not add to it. |
--list-profiles |
off | Print the delegation profiles this configuration carries, and exit. A value under env is printed as written, never as it resolves. |
--save-profile <name> |
not set | Save this invocation as a [[delegation_profiles]] row in the configuration the command read (~/.gdsgate/config.toml without --config), then run it. The row holds what the run settled on, --profile included; env values are kept as written, references unresolved. Written after every check passes and before the grant is minted. A row of that name is refused. |
--replace-profile |
off | Let --save-profile write over a row of the same name. |
--env <NAME=VALUE> |
not set | A variable for the --exec program. Repeatable. Added to the profile's env name by name; a name given here wins. VALUE may be ${env:NAME} or ${file:PATH}, read when the run starts. |
--ttl <secs> |
1800 |
Grant lifetime, 60 s to 24 h. With --exec it is also a deadline on the program: one still running when the window closes is stopped, and under --sandbox basic or strict that takes its whole process tree. The program is stopped the same way, and the grant revoked, when the terminal it runs on goes away (closed, or its host killed) or gdsgate is asked to terminate. A terminal a multiplexer keeps is not gone when its window detaches. |
--bind-key <dir> |
not set | Mint an agent-bound grant: write the credential bundle (key and certificate, mode 0600) into <dir> for an agent to present. The agent runs with GDSGATE_KEYSTORE_ROOT=<dir>. |
--exec [<prog>] |
not set | Mint an agent-bound grant, run <prog> with a local endpoint per granted resource, then revoke the grant when it exits. Args after -- are passed to <prog>. With --profile the value may be left off: the program then comes from the row, and the bare flag is what says to run it. |
--renewable |
off | Make the agent-bound certificate short-lived and renewed within the grant window, never past the TTL. When off, the certificate lives as long as the grant. Only with --bind-key or --exec. With --bind-key the agent renews it (gdsgate delegations renew); with --exec, gdsgate renews it and needs [enroll].endpoint. |
--model <channel> |
from the grant | Where the --exec program gets its model. gateway: through this gateway, as a delegated llm:call@<service> capability. direct: the program's own provider and credential. off: no model channel. The default is gateway when the grant names a model service, off otherwise. The value is checked against the grant and --sandbox. direct requires --sandbox none, and --allow-degraded does not waive that. Requires --exec. |
--agent-profile <name> |
from the program's file name | Which agent profile configures the --exec program. By default the program's file name is used (--exec /usr/local/bin/codex looks for codex); set it for a wrapper, a launcher or a renamed copy. An unknown name is refused. Requires --exec. |
--list-agent-profiles |
off | Print the agent profiles this run knows, with the documentation each was read from and the day it was read, and exit. |
--show-agent-profile <name> |
not set | Print that agent profile as a [[agent_profiles]] table with every field, and exit. A first comment line says whether it is the shipped row or one from the configuration. A configured row replaces the shipped one whole, so copy the entire table. |
--sandbox <profile> |
none |
Confine the --exec program: none, basic or strict, described below. Linux and Windows. Requires --exec. |
--sandbox-allow <path> |
not set | Extra path the sandboxed program may read and execute. Repeatable. |
--sandbox-listen <port> |
not set | Let this machine reach the caged program on its 127.0.0.1:<port>. Repeatable. For a sign-in callback or a development server opened from outside. Any process of any user on this machine reaches the port; nothing else the program listens on is reachable. Refused with --sandbox none. On Linux the port is taken on this host and each connection is carried in; on Windows the gdsgate-client-net service lets it in. |
--keep-run-dir |
off | Keep the run's directory (gdsgate-run-<id> in the temporary directory) after the run, and print where. It is the caged program's home, with its logs and configuration, and may hold its work and tokens; remove it yourself. Without the flag the directory is removed with the run; one left by a killed run is removed by the account's next --exec run. |
--sandbox-memory <MiB> |
half this machine's RAM, at least 1024 | Memory ceiling for a strict run. |
--sandbox-processes <n> |
512 |
How many processes a strict run may hold at once. |
--sandbox-cpu <percent> |
three quarters of this machine's cores | CPU ceiling for a strict run, as a percentage of one core: 100 is one core, 400 is four. |
--allow-degraded |
off | Run even though this host cannot deliver every property the profile promises. Without it, a shortfall refuses. |
The three limit flags are refused on profiles other than strict. 0 is
refused.
Without --bind-key or --exec the grant is for a person: present it with the
global --as <grant-id>.
The grant applies to every decision in the session: each SQL statement, apiserver request, tool call, model call and HTTP request. Each must be permitted by your current rights, the grant's live capabilities, and the resource the certificate is scoped to.
The grant is read from the registry on each decision. After it is revoked
(gdsgate delegations revoke) or expires, the next
operation is refused. A certificate that outlives its grant opens nothing.
What a grant carries into an ssh session¶
A grant carries a forward only when it names it:
| Token | What it carries |
|---|---|
ssh:connect@<host> |
The session: a shell, a command, SFTP, and the onward hop of a jump-host backend. |
ssh:forward@<host> |
ssh -L and ssh -R, both directions. |
ssh:agent@<host> |
ssh -A: the client's ssh-agent, carried into the session. |
None of the three implies another. A grant for forwarding names two tokens:
ssh:forward@<host> grants both -L and -R. To allow one direction only,
use policy (sshForwardLocal / sshForwardRemote, see
Policy → SSH -L and -R) or the backend
(allow_local_forward / allow_remote_forward, see
Configuration → Forward gating).
ssh:forward is refused unless you hold both sshForwardLocal and
sshForwardRemote yourself.
A forward disabled in [[connector.backends]] stays disabled whatever the grant
says, and policy is checked on every forward. Revoking the grant refuses the
session's next forward.
The onward hop of a jump-host backend is part of the session:
ssh:connect@<host> carries it, under --as and agent-bound alike, and a
revoked grant stops it at the next hop.
Saved delegations¶
--profile runs a saved delegation:
gdsgate delegations create --profile coding-agent --exec # run the program the row names
gdsgate delegations create --profile coding-agent # create the grant, print its id
The program runs only when --exec is given. Without it, the row's sandbox
settings are ignored; --sandbox on the command line without --exec is
refused.
A row may set environment for the program, such as an agent's credential by reference:
[[delegation_profiles]]
name = "coding-agent"
can = ["llm:call@models-prod", "db:read@pg-demo"]
exec = "acme-agent"
sandbox = "basic"
sandbox_allow = ["/opt/toolchain"]
model = "gateway"
env = { ACME_TOKEN = "${env:ACME_TOKEN}", NODE_ENV = "production" }
${env:NAME} reads the environment of whoever runs the command; ${file:/path}
reads a file and drops its trailing newline. A plain string is taken literally.
A reference that resolves to nothing refuses the run before the grant is
created.
# Agent-bound: read-only on one database, credential bundle for the agent.
gdsgate delegations create --can db:read@prod-pg --ttl 1800 --bind-key ./agent-creds
GDSGATE_KEYSTORE_ROOT=./agent-creds ./my-agent
# Run a program for the life of the grant, then auto-revoke.
gdsgate delegations create --can db:read@prod-pg --exec ./nightly-report.sh
Endpoints: what the program is given¶
--exec opens one local endpoint per resource the grant names and tells the
program where they are. The program gets addresses and no credentials: the key
and certificate stay in the gdsgate process. Every request is authorized and
stops when the grant is revoked.
There is one endpoint per resource: db:read@pg and db:write@pg share one
address, and the gateway enforces the difference per request. The endpoint is a
byte relay, so psql, kubectl, redis-cli and ssh -p connect to it
directly. A web endpoint is printed as http://127.0.0.1:<port> whatever the
application's scheme; the connector speaks TLS to the application.
An MCP endpoint also answers MCP's Streamable HTTP binding, protocol revision
2026-07-28. Point the agent's MCP client at http://127.0.0.1:<port>/, or,
for a client that starts a program, at gdsgate mcp bridge 127.0.0.1:<port>.
The binary is in the sandbox's filesystem allowlist, and each bridge process
counts against --sandbox strict's process limit.
A web-egress endpoint is a forward proxy; do not use it as a base URL. When
the grant names one, the run sets $HTTP_PROXY and $HTTPS_PROXY, in both
cases, to that endpoint, and $NO_PROXY=127.0.0.1,localhost,::1. $ALL_PROXY
is not set. With two egress resources the variables name the first; the second
is in $GDSGATE_ENDPOINTS. When the catalogue cannot be read at start, no proxy
variable is set and the run reports it.
The program reads them from these environment variables:
| Variable | Value |
|---|---|
GDSGATE_ENDPOINTS |
resource=127.0.0.1:port, comma separated, for example prod-pg=127.0.0.1:14500,corp=127.0.0.1:14501. A resource name is [A-Za-z0-9._-]+, so splitting on , then = is unambiguous. Unset when the grant names no resources. |
GDSGATE_DELEGATION_ID |
The grant id. It authorizes nothing. |
HTTP_PROXY / http_proxy, HTTPS_PROXY / https_proxy |
http://127.0.0.1:<port> of the grant's web-egress resource, all four spellings set to the same value. Unset where the grant names none. |
NO_PROXY / no_proxy |
127.0.0.1,localhost,::1, set together with the pair above. |
Before the program starts, the run asks each granted web-egress resource
whether its backend has
inspect = true. A resource
that does not answer, an older connector included, is treated as not inspecting.
When one answers inspect, the run creates a certificate root for this run and
points the program's trust at it:
| Variable | Value |
|---|---|
SSL_CERT_FILE, REQUESTS_CA_BUNDLE, CURL_CA_BUNDLE, NODE_EXTRA_CA_CERTS, GIT_SSL_CAINFO, AWS_CA_BUNDLE, DENO_CERT |
All set to one file: this host's trust roots, followed by the run's root. Unset when no granted resource inspects. |
The JVM, .NET, and programs that pin a certificate read none of these and do not work through an inspecting resource; the run says so at start-up.
The same list is printed when the program starts. A program with a known agent profile is also configured from it.
gdsgate delegations create --can db:read@prod-pg --sandbox basic --exec ./agent
# delegation dl-… created (agent-bound, 1 capabilities, valid 1800s); running ./agent
# sandbox: basic, Landlock FullyEnforced, netns yes, …
# prod-pg -> 127.0.0.1:14500
gdsgate delegations create --can web:tunnel@outbound --sandbox basic --exec ./fetcher
# delegation dl-… created (agent-bound, 1 capabilities, valid 1800s); running ./fetcher
# sandbox: basic, Landlock FullyEnforced, netns yes, …
# outbound -> http://127.0.0.1:14500 (the way out; $HTTP_PROXY, not a base URL)
gdsgate delegations create --can web:read@outbound --can web:write@outbound --sandbox basic --exec ./fetcher
# the way out `outbound` reads what it carries. This run ends the program's TLS itself, with a
# certificate root generated for this run alone, and the connector decides every request inside
# it by its method and its path — so what the program spends is `web:read` and `web:write`
# and not the channel verb. The root is in this process's memory, is trusted by nothing but
# the program this run starts, and is gone when the run ends. A program that pins a certificate
# cannot be served this way.
# delegation dl-… created (agent-bound, 2 capabilities, valid 1800s); running ./fetcher
# sandbox: basic, Landlock FullyEnforced, netns yes, …
# outbound -> http://127.0.0.1:14500 (the way out; $HTTP_PROXY, not a base URL)
Where the endpoints listen:
| Sandbox | Linux | Windows |
|---|---|---|
basic, strict |
inside the sandbox's network namespace, reachable only from the sandbox; ports from 14500 upwards in the order the capabilities were granted |
host loopback on kernel-chosen ports; only the run's container is let through, by gdsgate-client-net (see The sandbox on Windows) |
none |
host loopback on kernel-chosen ports, reachable by any user on the machine, as with gdsgate db proxy |
same |
Under --sandbox none the program runs as you, and your credential and keys are
readable to it; the run prints what is and is not enforced before it starts.
When the shell already sets $HTTP_PROXY or a related variable, the run warns
and replaces it for the program. A client with a proxy configured in a file
(~/.curlrc, pip.conf) bypasses the egress resource. Under basic and
strict the environment is cleared first and the endpoints are the only route
out.
When the program exits, the endpoints close and the grant is revoked.
Under --sandbox basic and strict the run prints everything before the
program starts. While it runs the terminal belongs to the program: per-connection
lines go to the log, and warnings and failures are printed when the program
exits. Under --sandbox none the same lines follow the program's start.
Agent profiles¶
A profile says where one agent reads its model address and what form and
location its MCP configuration takes. It is chosen by the file name of the
--exec program, or by --agent-profile <name> when the
program is a wrapper.
gdsgate delegations create --list-agent-profiles
# claude checked 2026-08-03 https://code.claude.com/docs/en/env-vars + …
# codex checked 2026-08-03 https://developers.openai.com/codex/mcp + …
# openclaw checked 2026-08-03 https://docs.openclaw.ai/cli/mcp + …
# opencode checked 2026-08-03 https://opencode.ai/docs/mcp-servers/ + …
# pi checked 2026-08-03 https://pi.dev/docs/latest/usage + …
The date is when the row was last checked against its source. When an agent
release renames a variable, nothing fails and the agent talks to the wrong
address; re-check old rows against the source.
The shipped rows, as of that date:
| Agent | Model address | MCP configuration |
|---|---|---|
claude |
ANTHROPIC_BASE_URL |
the rendered file, passed as --mcp-config <file> --strict-mcp-config |
codex |
configuration key (openai_base_url; a model_providers.<id> table also needs a name, which one key cannot give) |
~/.codex/config.toml, [mcp_servers.<name>] with url |
opencode |
configuration key (provider.<id>.options.baseURL) |
mcp in the configuration; OPENCODE_CONFIG points at the rendered file, ~/.config/opencode/opencode.json under a cage |
openclaw |
configuration key (models.providers.<id>.baseUrl) |
mcp.servers.<name> with transport = "streamable-http", in ~/.openclaw/openclaw.json |
pi |
configuration key (providers.<id>.baseUrl, in ~/.pi/agent/models.json) |
none: pi documents that it intentionally ships no built-in MCP client |
The MCP configuration is set for every agent that has an MCP client: the file is
rendered and installed where the agent looks, named by a variable, or passed on
the command line. The model address is set by environment variable for one
agent and by configuration key for the rest. A key is written only under a
cage, into the run's own $HOME; without a cage gdsgate does not write into
your home. The shipped rows leave model_config_key empty where the key would
name a provider id only you know. When the address could not be set, the run
prints the agent, the reason, and the address to set by hand.
A program with no profile gets no guessed configuration. The run lists what it was given:
no agent profile for `some-agent`: this run does not know which variables or files it reads,
and a guessed one is an agent that looks configured and is not.
it was told: $GDSGATE_DELEGATION_ID, and $GDSGATE_ENDPOINTS with
corp -> 127.0.0.1:14500 — MCP, answering Streamable HTTP; `gdsgate mcp bridge` pipes it to a stdio client
gpt -> 127.0.0.1:14501 — the model endpoint, for whichever base-URL variable this agent reads
stdio-only client: /usr/bin/gdsgate mcp bridge 127.0.0.1:14500
to have this settled for you next time, add a row for it under [[agent_profiles]] in the
configuration — a profile is data, so no release of gdsgate is involved.
To add a profile, add a row under
[[agent_profiles]] in the configuration.
A row with the same name as a shipped one replaces it.
--sandbox basic and --sandbox strict¶
Both limit what the program can read and reach while it holds the grant. Policy at the gateway still limits what the grant may do.
basic promises seven properties; strict adds two. The run is refused if this
host cannot deliver a promised property; --allow-degraded runs it anyway with
a warning. The properties are checked on the host before the child starts, and
inside the child before the program runs.
On Linux:
| Property | How | basic |
strict |
|---|---|---|---|
| The filesystem is deny-by-default: the program sees what it was given and nothing else | Landlock (ABI 3 or newer) | ✓ | ✓ |
| No IP network beyond the endpoints above | An empty network namespace | ✓ | ✓ |
| The environment is emptied and rebuilt from an allowlist | env_clear + allowlist | ✓ | ✓ |
| Inherited descriptors are closed on exec | close-on-exec | ✓ | ✓ |
no_new_privs |
prctl |
✓ | ✓ |
The program is killed if gdsgate dies |
PR_SET_PDEATHSIG |
✓ | ✓ |
| The program's whole process tree dies with the run | A private PID namespace whose first process is gdsgate's |
✓ | ✓ |
| No socket in an address family the network namespace does not confine | seccomp-bpf | not enforced | ✓ |
| Memory, process-count and CPU limits | cgroup v2 | not enforced | ✓ |
Allowed on the filesystem under either profile: the system runtime, a minimal
/etc, the usual character devices, the working directory, a private directory
that becomes $HOME and $TMPDIR, the program's installation prefix, and paths
given with --sandbox-allow. Not allowed: the real home directory, /proc, and
the credential bundle.
On Windows the same properties are built from an AppContainer and a job object; see The sandbox on Windows.
gdsgate doctor reports what this host can
enforce.
The difference between them¶
On Linux, basic does not block unix-domain sockets: a program can connect by
path to any host daemon whose socket permissions admit it, for example
/run/docker.sock or the session bus. strict refuses to create sockets in
address families the network namespace does not confine; socket() returns
EPERM. socketpair still works.
gdsgate doctor lists the sensitive sockets it finds on this host.
strict also holds the whole run under memory, process-count and CPU limits; a
program that exhausts memory can end the run. It needs a cgroup v2 subtree
delegated to this account: on a systemd host usually user@<uid>.service,
inside a container delegated explicitly. Without one, strict is refused;
basic is unaffected.
Security limitations¶
On Linux:
strictalso refuses other system calls as hardening; this list is not complete.unshareis refused andclone3is not.- A refused call returns an error. A call through another architecture's
system-call table is killed, so 32-bit binaries do not run under
strict. - Signals work as usual:
Ctrl-Creaches the program, and its exit code or "killed by signal N" is passed on. - Neither profile protects against a kernel exploit; use a virtual machine for that.
The sandbox on Windows¶
The same properties, built from an AppContainer and a job object:
| Property | On Windows |
|---|---|
| filesystem | the working directory, the private directory, the program's directory and --sandbox-allow, granted for the run and removed after |
| network | no network capability, loopback included; needs the Base Filtering Engine service running |
| environment, descriptors | emptied and rebuilt; the program gets its three standard handles only |
| no-new-privs | held by the container token |
| parent death, process tree, limits | the job ends every process in it when the run ends; strict limits apply to the job |
| syscalls | no system-call filter; reported as held because a container cannot open a daemon's named pipe or unix socket |
The line a run prints names these: sandbox: basic, AppContainer yes, network
yes, ....
The gdsgate-client-net service, registered by the installer, lets the run's
container reach its own endpoint ports for the length of the run. No other
loopback address is reachable from the container, and no other process reaches
those ports.
For the length of the run the same service also gives the container read access
to the mount manager (needed to resolve C:\... paths) and read/write access to
NUL.
A program started from a console window runs on its own pseudoconsole, hosted by
OpenConsole.exe beside gdsgate.exe; redirected streams stay redirected.
gdsgate doctor reports it as sandbox.console.
| Symptom | Cause | What to do |
|---|---|---|
A grant that names a resource is refused under basic or strict; gdsgate doctor says why |
gdsgate-client-net is not running |
sc.exe start gdsgate-client-net from an elevated prompt |
delegate reports after the program exits that the container lost its access |
the service stopped during the run | start the service and run again |
| Screen-reading calls (PowerShell progress, for example) fail with an access error | OpenConsole.exe is missing beside gdsgate.exe |
reinstall from the .msi |
| The run is refused, naming the working directory | this account cannot change the directory's access list (for example C:\Windows\System32, where a scheduled task starts) |
run from a directory of your own |
| The network property fails | the Base Filtering Engine service is not running | start it |
A killed run leaves its grants to the container behind. The next run under the
same account removes them, the container, and the run's directory (kept only
with --keep-run-dir).
What the audit chain says about the sandbox¶
Every --exec run reports its sandbox to the gateway, which seals one audit row
against the grant. The row lists, property by property, what was measured inside
the sandbox, and whether --allow-degraded was used. --sandbox none runs
report too.
gdsgate --config authority.toml authority audit list --class client-assertion --limit 1
# # time class action code actor(verified) target outcome
# 1754006400 ClientAssertion sandbox.claim SBX-0101 alice 5f1c9a02b7d4 Failure
# `- profile=basic landlock=NotEnforced cage_achieved=network,environment,descriptors,no_new_privs,parent_death,process_tree cage_missing=filesystem allow_degraded=true
cage_achieved lists the properties in force and cage_missing those the
profile promised and the run did not get; both are written even when empty. A
property in neither list is not promised by the profile: a basic run has no
syscalls, so the program could reach a host daemon by socket path.
outcome is Success when the sandbox matched the requested profile and
Failure when it fell short. The rest of the row is reported by the client; see
the ClientAssertion class.
The gateway checks only that the caller owns the grant.
If the row cannot be sealed, the program is killed and the grant revoked.
gdsgate delegations list¶
Lists the grants you own. Columns: id, status, can. status is the
remaining TTL, or expired, or revoked, by id or by an owner-revocation.
--wide adds owner, created and expires. --json prints one object per
grant, with times as Unix seconds.
gdsgate delegations revoke <id> | --all | --owner <user>¶
Revokes delegations. Effective on the grant's next use: a revoked grant is refused at the agent's next request even though its certificate is still valid.
| Form | Effect |
|---|---|
gdsgate delegations revoke <id> |
Revoke one grant you own by id. Revoking an unknown grant, or one you do not own, is a no-op. |
gdsgate delegations revoke --all |
Revoke all of your own grants at once. No need to list ids. |
gdsgate delegations revoke --owner <user> |
Revoke all grants owned by another user. Admin only, gated by the disableUser policy action over that user. <user> is the bare subject, for example their OIDC sub. |
--all and --owner revoke every grant the owner created before now, in one
step. Grants created afterwards are unaffected. Use --owner when offboarding a
user. Both are idempotent.
gdsgate delegations status [--json]¶
Reports the delegation grant in the local credential
bundle, the grant an agent-bound certificate presents. Prints its id, owner,
capabilities, and remaining validity. Point GDSGATE_KEYSTORE_ROOT at the bundle
directory gdsgate delegations create --bind-key wrote. An agent runs it before a task to
avoid starting on an expired grant. An --exec run writes no bundle; its
program gets the grant id in GDSGATE_DELEGATION_ID.
The check is local and does not contact the gateway. A revoked grant that has
not expired still reads valid here; the next access is refused.
| Flag | Purpose |
|---|---|
--json |
Emit machine-readable JSON (id, owner, can, not_before_unix, not_after_unix, seconds_remaining, status) for an agent to parse. |
status is valid, expired, or not_yet_valid.
$ GDSGATE_KEYSTORE_ROOT=./agent-creds gdsgate delegations status
delegation a1b2c3
owner: User::"alice"
can: db:read@prod-pg
status: valid
expires in: 28m
$ GDSGATE_KEYSTORE_ROOT=./agent-creds gdsgate delegations status --json
{"can":["db:read@prod-pg"],"id":"a1b2c3","not_after_unix":1787272080,"not_before_unix":1787270280,"owner":"User::\"alice\"","seconds_remaining":1680,"status":"valid"}
gdsgate delegations renew [--endpoint <url>]¶
Rolls the agent-bound certificate in the local bundle forward within the grant
window, only for a grant delegated --renewable. Generates a
fresh key, proves possession with the current one, and replaces the bundle's
certificate. The new certificate never outlives the grant's TTL, and a
non-renewable grant is refused. Point GDSGATE_KEYSTORE_ROOT at the bundle and
renew before the certificate lapses; after it lapses, delegate again.
--endpoint defaults to [enroll].endpoint.
status renew