Skip to content

gate_tokens

gate_tokens

Token CRUD for gate server per-task authentication.

Each task gets a prefixed random 128-bit hex token scoped to its project. Tokens are stored in state_root()/gate/tokens.json and read by the standalone gate server process (which receives the file path via --token-file).

Token format: terok-g-<32 hex chars> (e.g. terok-g-a1b2c3…).

File format::

{"terok-g-<hex>": {"project": "<project_id>", "task": "<task_id>"}}

token_file_path(cfg=None)

Return the path to the shared token file.

Source code in src/terok_sandbox/gate_tokens.py
def token_file_path(cfg: SandboxConfig | None = None) -> Path:
    """Return the path to the shared token file."""
    return (cfg or SandboxConfig()).token_file_path

create_token(project_id, task_id, cfg=None)

Generate a 128-bit hex token, persist atomically, and return it.

Uses secrets.token_hex(16) for cryptographic randomness. Atomic write via tempfile + os.replace().

Source code in src/terok_sandbox/gate_tokens.py
def create_token(project_id: str, task_id: str, cfg: SandboxConfig | None = None) -> str:
    """Generate a 128-bit hex token, persist atomically, and return it.

    Uses ``secrets.token_hex(16)`` for cryptographic randomness.
    Atomic write via ``tempfile`` + ``os.replace()``.
    """
    token = f"terok-g-{secrets.token_hex(16)}"
    path = token_file_path(cfg)
    with _token_lock(path):
        tokens = _read_tokens(path)
        tokens[token] = {"project": project_id, "task": task_id}
        _write_tokens(path, tokens)
    return token

revoke_token_for_task(project_id, task_id, cfg=None)

Remove all tokens for the given project+task pair. Idempotent.

Source code in src/terok_sandbox/gate_tokens.py
def revoke_token_for_task(project_id: str, task_id: str, cfg: SandboxConfig | None = None) -> None:
    """Remove all tokens for the given project+task pair.  Idempotent."""
    path = token_file_path(cfg)
    with _token_lock(path):
        tokens = _read_tokens(path)
        to_remove = [
            t
            for t, info in tokens.items()
            if info.get("project") == project_id and info.get("task") == task_id
        ]
        if not to_remove:
            return
        for t in to_remove:
            del tokens[t]
        _write_tokens(path, tokens)