client

package
v0.2.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 29, 2026 License: MPL-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package client is the small HTTP client the txco CLI uses to talk to a running chassis admin server.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ActivateResponse

type ActivateResponse struct {
	PriorVersionNumber *int64 `json:"prior_version_number,omitempty"`
	VersionNumber      int64  `json:"version_number"`
	StructuredURL      string `json:"structured_url,omitempty"`
}

type AddHostnameRequest

type AddHostnameRequest struct {
	Hostname string `json:"hostname"`
	Stack    string `json:"stack"`
}

AddHostnameRequest is the wire body POST /v1/tenants/{t}/hostnames expects. Hostname is canonicalized server-side; the response shows the canonical form back.

type BootstrapBrowserResponse

type BootstrapBrowserResponse struct {
	Token            string `json:"token"`
	ExpiresInSeconds int    `json:"expires_in_seconds"`
	URL              string `json:"url"`
}

BootstrapBrowserAuth mints a single-use exchange token. The returned URL is what the user opens to complete login in their browser; the token is embedded in the URL's hash fragment.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client wraps an *http.Client and a Target.

func New

func New(t Target) *Client

func (*Client) Activate

func (c *Client) Activate(ctx context.Context, name string, versionNumber int64) (*ActivateResponse, error)

Activate: POST /stacks/{name}/activate

func (*Client) AddHostname

func (c *Client) AddHostname(ctx context.Context, req AddHostnameRequest) (*Hostname, error)

AddHostname claims a hostname for the target tenant against a specific stack. Server canonicalizes the hostname (lowercase, port- stripped, trailing-dot-stripped) so the returned row may differ from the request literal.

func (*Client) Addr

func (c *Client) Addr() string

Addr returns the configured chassis URL. Useful for auth commands that want to echo the URL they're talking to without re-resolving.

func (*Client) AttachHostname

func (c *Client) AttachHostname(ctx context.Context, hostname, stack string) (*Hostname, error)

AttachHostname binds an existing hostname (claimed earlier via AddHostname without --stack, or being re-pointed at a different stack) to the given stack within the active tenant.

func (*Client) BootstrapBrowserAuth

func (c *Client) BootstrapBrowserAuth(ctx context.Context, label string) (*BootstrapBrowserResponse, error)

BootstrapBrowserAuth signs a POST to /auth/browser/bootstrap and returns the mint response. The CLI then `open`s the URL (or prints it for the user to paste into a browser).

func (*Client) ConsumeInvitation

func (c *Client) ConsumeInvitation(ctx context.Context, req ConsumeInvitationRequest) (*DevEnrollResponse, error)

ConsumeInvitation redeems a token in exchange for a fresh actor + key. Unsigned endpoint; the token is the credential.

func (*Client) CreateDraft

func (c *Client) CreateDraft(ctx context.Context, name, from string) (int64, error)

CreateDraft: POST /stacks/{name}/draft from: "active" to clone the currently-active version, "<N>" to clone a specific version_number, or "" for an empty draft.

func (*Client) CreateHostnameChallenge

func (c *Client) CreateHostnameChallenge(ctx context.Context, hostname, method string, force bool) (*HostnameChallenge, error)

CreateHostnameChallenge issues a fresh DNS-TXT or HTTP-01 challenge for the named hostname. Server returns the token + human-readable setup instructions the CLI prints verbatim.

func (*Client) CreateInvitation

func (c *Client) CreateInvitation(ctx context.Context, req CreateInvitationRequest) (*CreateInvitationResponse, error)

CreateInvitation mints a new invitation. Signed.

func (*Client) CreateSecret

func (c *Client) CreateSecret(ctx context.Context, req CreateSecretRequest) (*Secret, error)

CreateSecret stores an operator-supplied value. Server returns metadata only — the operator already has the cleartext.

func (*Client) CreateTenant

func (c *Client) CreateTenant(ctx context.Context, req CreateTenantRequest) (*Tenant, error)

CreateTenant mints a new tenant. Server-side gated by super_admin (or basic-auth / open operator). Returns the new row including the generated tenant_id. Signed.

func (*Client) DeleteDraftFile

func (c *Client) DeleteDraftFile(ctx context.Context, name string, versionNumber int64, path, baseHash string) (*DeleteFileResponse, error)

DeleteDraftFile: DELETE /stacks/{name}/versions/{n}/files

baseHash is required (server returns 400 for blind deletes).

func (*Client) DevEnroll

func (c *Client) DevEnroll(ctx context.Context, secret string, body DevEnrollRequest) (*DevEnrollResponse, error)

DevEnroll exchanges a shared secret for an actor + key in one shot. Unsigned (the endpoint is unprotected); we send X-Txco-Enroll-Secret as the bootstrap credential.

func (*Client) DiffVersions

func (c *Client) DiffVersions(ctx context.Context, name string, v1, v2 int64) (*DiffResponse, error)

DiffVersions: GET /stacks/{name}/diff?v1=&v2=

func (*Client) GenerateSecret

func (c *Client) GenerateSecret(ctx context.Context, req GenerateSecretRequest) (*SecretWithValue, error)

GenerateSecret mints a fresh random value server-side and returns it once. The caller is responsible for surfacing the value to the operator (e.g. printing to terminal) — no other endpoint can retrieve it later.

func (*Client) GetSecret

func (c *Client) GetSecret(ctx context.Context, name, stack string) (*Secret, error)

GetSecret returns metadata for one secret. `stack` selects the stack-scoped row; empty string selects the tenant-wide row.

func (*Client) GetStack

func (c *Client) GetStack(ctx context.Context, name string) (*StackRecord, error)

GetStack: GET /stacks/{name}

func (*Client) GetTrace

func (c *Client) GetTrace(ctx context.Context, rid string, full bool) (*TraceResponse, []byte, error)

GetTrace fetches the aggregate trace document for rid. When full is true the response also embeds in/out payloads (only present when the chassis is running with --trace-mode=full).

Returns *TraceNotFoundError if the server returns 404 — handlers can type-assert to print a friendlier error.

Also returns the raw response bytes so callers that want to emit the untouched JSON (e.g. `txco trace --json`) don't have to re-encode.

func (*Client) GetVersion

func (c *Client) GetVersion(ctx context.Context, name string, versionNumber int64, includeContent bool) (*VersionDetail, error)

GetVersion: GET /stacks/{name}/versions/{n}?include=content

func (*Client) GrantMember

func (c *Client) GrantMember(ctx context.Context, req GrantMemberRequest) (*TenantMember, error)

GrantMember upserts a membership in the caller's target tenant. Server gates on actor:*:invite in the tenant. Returns the freshly- written row so callers can echo "granted actor_X: opstack:*:read" without a follow-up read.

func (*Client) HeadCompute

func (c *Client) HeadCompute(ctx context.Context, alg, digest string) (bool, error)

HeadCompute reports whether a compute artifact is already present, so apply can skip re-uploading unchanged modules.

func (*Client) HostnameStatusOf

func (c *Client) HostnameStatusOf(ctx context.Context, hostname string) (*HostnameStatus, error)

HostnameStatusOf reads the read-only state of a hostname (binding + current active/expired challenges) without rotating anything. Counterpart to CreateHostnameChallenge for "I just want to see what token is in DNS today." See internal docs/todo-custom-domains.md §6a.

func (*Client) ListBrowserSessions

func (c *Client) ListBrowserSessions(ctx context.Context) ([]SessionRecord, error)

ListBrowserSessions returns every session for the target tenant, newest first.

func (*Client) ListHostnames

func (c *Client) ListHostnames(ctx context.Context, history bool) ([]Hostname, error)

ListHostnames returns the active hostnames bound to the target tenant. `history=true` flips to all-rows mode (including revoked ones) for debugging "who used to own this?".

func (*Client) ListInvitations

func (c *Client) ListInvitations(ctx context.Context) ([]Invitation, error)

ListInvitations returns all invitations (newest first). Signed.

func (*Client) ListOps

func (c *Client) ListOps(ctx context.Context, prefix string) ([]Op, error)

ListOps returns rules at-or-under the given stack prefix. Empty prefix returns all rules.

func (*Client) ListSecrets

func (c *Client) ListSecrets(ctx context.Context) ([]Secret, error)

ListSecrets returns active secrets in the active tenant (both tenant-wide and stack-scoped). Metadata only — the wire never carries a value field on this path.

func (*Client) ListStacks

func (c *Client) ListStacks(ctx context.Context) ([]StackRecord, error)

ListStacks: GET /stacks

func (*Client) ListTenantMembers

func (c *Client) ListTenantMembers(ctx context.Context) ([]TenantMember, error)

ListTenantMembers returns the active membership rows for the caller's target tenant (set via Target.Tenant). Server enforces actor:read in this tenant. Signed.

func (*Client) ListTenants

func (c *Client) ListTenants(ctx context.Context) ([]Tenant, error)

ListTenants returns the tenants the caller can see. The chassis filters by membership (or returns all for super_admin); the client just renders. Signed.

func (*Client) ListTraces

func (c *Client) ListTraces(ctx context.Context, limit int, grep string) (*TraceListResponse, error)

ListTraces fetches recent traces. See ListTracesETag for the ETag-aware variant; this thin wrapper is kept for callers that don't care about caching.

func (*Client) ListTracesETag

func (c *Client) ListTracesETag(ctx context.Context, limit int, grep, ifNoneMatch string) (*TraceListResponse, string, bool, error)

ListTracesETag fetches recent traces, sending If-None-Match when ifNoneMatch is non-empty. Returns (resp, etag, notModified, err):

  • notModified=true means the server returned 304 and resp is nil; the caller should keep using its cached copy.
  • on a fresh 200 response, etag is the server's new ETag — pass it on the next call to short-circuit if nothing changed.

limit<=0 means the server default (50; server caps at 500). When grep is non-empty the server filters to traces whose files contain the substring (case-insensitive).

func (*Client) ListVersions

func (c *Client) ListVersions(ctx context.Context, name string) ([]VersionRecord, error)

ListVersions: GET /stacks/{name}/versions

func (*Client) PatchDraftFile

func (c *Client) PatchDraftFile(ctx context.Context, name string, versionNumber int64, path, content, baseHash string) (*PatchFileResponse, error)

PatchDraftFile: PATCH /stacks/{name}/versions/{n}/files

Single-file upsert with optimistic concurrency. baseHash is the content_hash the caller previously observed; pass "" to create a new file. The server returns 404 if you pass a non-empty baseHash for a path that doesn't exist, and 409 for hash mismatch or create-collision. decodeError surfaces those with their `current_hash` so the caller can present a useful conflict UI.

func (*Client) PutCompute

func (c *Client) PutCompute(ctx context.Context, alg, digest, engine string, wasm []byte) error

PutCompute uploads a content-addressed compute module. The server verifies sha256(body)==digest; the upload is idempotent. engine (e.g. "wazero") is recorded in the artifact manifest.

func (*Client) PutDraftFiles

func (c *Client) PutDraftFiles(ctx context.Context, name string, versionNumber int64, files []StackFile) (*PutFilesResponse, error)

PutDraftFiles: PUT /stacks/{name}/versions/{n}/files

func (*Client) RemoveHostname

func (c *Client) RemoveHostname(ctx context.Context, hostname string) error

RemoveHostname soft-deletes a hostname binding. Idempotent — the server returns 200 with revoked=true whether or not the row was present.

func (*Client) RevokeBrowserSession

func (c *Client) RevokeBrowserSession(ctx context.Context, sessionID string) error

RevokeBrowserSession revokes one session by id. Idempotent at the server.

func (*Client) RevokeInvitation

func (c *Client) RevokeInvitation(ctx context.Context, invitationID string) (*RevokeInvitationResponse, error)

RevokeInvitation marks an invitation revoked by id. Signed.

func (*Client) RevokeKey

func (c *Client) RevokeKey(ctx context.Context, keyID string) (*RevokeResponse, error)

RevokeKey signs a POST /auth/keys/<id>/revoke.

func (*Client) RevokeMember

func (c *Client) RevokeMember(ctx context.Context, actorID string) error

RevokeMember soft-deletes a membership for the given actor in the caller's target tenant. Server gates on actor:*:invite. Idempotent — revoking an absent/already-revoked membership returns ok.

func (*Client) RevokeSecret

func (c *Client) RevokeSecret(ctx context.Context, name, stack string) error

RevokeSecret soft-deletes the active row. Returns nil on 204.

func (*Client) RotateSecret

func (c *Client) RotateSecret(ctx context.Context, name, stack, newValue string) (*Secret, error)

RotateSecret writes a new version under the same name with an operator-supplied value.

func (*Client) RotateSecretGenerated

func (c *Client) RotateSecretGenerated(ctx context.Context, name, stack string, byteLen int) (*SecretWithValue, error)

RotateSecretGenerated mints a fresh random value, writes a new version under the same name, and returns the value once.

func (*Client) UpdateSecretDescription

func (c *Client) UpdateSecretDescription(ctx context.Context, name, stack, newDescription string) (*Secret, error)

UpdateSecretDescription PATCHes the description only. The server rejects any body that includes a `name` field (immutable per design §1.7).

func (*Client) ValidateVersion

func (c *Client) ValidateVersion(ctx context.Context, name string, versionNumber int64) (*ValidateResponse, error)

ValidateVersion: POST /stacks/{name}/versions/{n}/validate

Server returns 200 with `{"ok": true|false, "errors": [...]}` so a failed parse is not an HTTP error — the caller decides whether `!ok` should block a downstream activate.

func (*Client) VerifyHostname

func (c *Client) VerifyHostname(ctx context.Context, hostname string) (*HostnameVerifyResponse, error)

VerifyHostname runs the active challenge for the named hostname (either DNS or HTTP method, whichever was issued). On success returns the verified_at timestamp; on failure decodes the server's "verification_failed" body so the CLI can show last_error.

func (*Client) Whoami

func (c *Client) Whoami(ctx context.Context) (*WhoamiResponse, error)

Whoami calls GET /auth/whoami with whatever credentials the target has configured. Useful to confirm signed-auth wiring.

type ConsumeInvitationRequest

type ConsumeInvitationRequest struct {
	Token        string `json:"token"`
	PublicKeyB64 string `json:"public_key_b64"`
	Algorithm    string `json:"algorithm"`
	Label        string `json:"label,omitempty"`
	Kind         string `json:"kind,omitempty"`
}

ConsumeInvitationRequest is the wire body POST /auth/invitations/consume expects. Unsigned endpoint — the token IS the authentication.

type CreateInvitationRequest

type CreateInvitationRequest struct {
	Label        string   `json:"label,omitempty"`
	Kind         string   `json:"kind,omitempty"`
	TTLSeconds   int      `json:"ttl_seconds,omitempty"`
	Capabilities []string `json:"capabilities,omitempty"`
}

CreateInvitationRequest is the wire body POST /auth/invitations expects.

Capabilities is the list of 3-segment capability strings the resulting member receives. Empty defaults to admin:all on the server (back-compat with pre-phase-6 CLIs).

type CreateInvitationResponse

type CreateInvitationResponse struct {
	InvitationID string `json:"invitation_id"`
	Token        string `json:"token"`
	ExpiresAt    string `json:"expires_at"`
}

CreateInvitationResponse is what the server returns once the token is minted. Token is the one-shot raw secret — it never appears in the DB or in any subsequent response.

type CreateSecretRequest

type CreateSecretRequest struct {
	Name        string `json:"name"`
	Value       string `json:"value"`
	Description string `json:"description,omitempty"`
	Stack       string `json:"stack,omitempty"`
}

CreateSecretRequest mirrors the JSON shape POST /secrets accepts. Value is the operator-supplied cleartext; the server NEVER returns it back in any response.

type CreateTenantRequest

type CreateTenantRequest struct {
	Slug string `json:"slug"`
	Name string `json:"name,omitempty"`
}

CreateTenantRequest is the wire body POST /v1/tenants expects. Slug is the durable handle and is required; Name is optional display text.

type DeleteFileResponse

type DeleteFileResponse struct {
	Path         string `json:"path"`
	Deleted      bool   `json:"deleted"`
	ManifestHash string `json:"manifest_hash"`
}

type DevEnrollRequest

type DevEnrollRequest struct {
	PublicKeyB64 string `json:"public_key_b64"`
	Algorithm    string `json:"algorithm"`
	Label        string `json:"label,omitempty"`
	Kind         string `json:"kind,omitempty"`
}

DevEnrollRequest is the wire body /auth/dev/enroll expects.

type DevEnrollResponse

type DevEnrollResponse struct {
	ActorID      string   `json:"actor_id"`
	KeyID        string   `json:"key_id"`
	Capabilities []string `json:"capabilities"`
	// TenantSlug is the tenant the new actor was placed in. Always
	// "default" for bootstrap-local; the invitation's tenant for
	// accept. Empty if the server is older than phase 5; the CLI
	// falls back to "default" in that case.
	TenantSlug string `json:"tenant_slug,omitempty"`
	// SuperAdmin reports whether this enrolment yielded chassis-wide
	// super-admin (first-boot bootstrap only).
	SuperAdmin bool `json:"super_admin,omitempty"`
}

DevEnrollResponse is the wire response /auth/dev/enroll returns.

type DiffEntry

type DiffEntry struct {
	Path     string `json:"path"`
	Change   string `json:"change"`
	FromHash string `json:"from_hash,omitempty"`
	ToHash   string `json:"to_hash,omitempty"`
}

type DiffResponse

type DiffResponse struct {
	V1      int64       `json:"v1"`
	V2      int64       `json:"v2"`
	Equal   bool        `json:"equal"`
	Entries []DiffEntry `json:"entries,omitempty"`
}

type ErrorResponse

type ErrorResponse struct {
	Error  string         `json:"error"`
	Detail map[string]any `json:"detail,omitempty"`
}

type GenerateSecretRequest

type GenerateSecretRequest struct {
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`
	Stack       string `json:"stack,omitempty"`
	ByteLen     int    `json:"byte_len,omitempty"`
}

GenerateSecretRequest is the body for POST /secrets/generate. The server mints ByteLen random bytes (default 32) and returns the base64-url encoded value exactly once.

type GrantMemberRequest

type GrantMemberRequest struct {
	ActorID      string   `json:"actor_id"`
	Capabilities []string `json:"capabilities"`
}

GrantMemberRequest is the wire body for POST .../auth/members. The server treats this as an upsert: re-granting an existing member replaces the capability set (and clears revoked_at).

type HTTPError

type HTTPError struct {
	StatusCode int
	Status     string
	Code       string
	Detail     map[string]any
	Raw        string
}

HTTPError captures a server-side JSON error response in a typed form so callers can branch on status (`errors.As`) without parsing the rendered string. The `Code` field is the `error` value the chassis writes (e.g. `base_hash_mismatch`, `file_not_found`); the `Detail` map carries actionable context (current_hash, path, etc.).

func (*HTTPError) Error

func (e *HTTPError) Error() string

type Hostname

type Hostname struct {
	ID         string `json:"id"`
	Hostname   string `json:"hostname"`
	TenantID   string `json:"tenant_id"`
	Stack      string `json:"stack"`
	CreatedAt  string `json:"created_at"`
	CreatedBy  string `json:"created_by,omitempty"`
	RevokedAt  string `json:"revoked_at,omitempty"`
	VerifiedAt string `json:"verified_at,omitempty"`
}

Hostname mirrors a tenant_hostnames row returned by the admin API.

type HostnameChallenge

type HostnameChallenge struct {
	ID           string `json:"id"`
	Method       string `json:"method"`
	Token        string `json:"token"`
	ExpiresAt    string `json:"expires_at"`
	Instructions string `json:"instructions"`
	// Reused is true when the server returned a pre-existing active
	// challenge (idempotent path, status 200) instead of minting a new
	// one. The CLI prints a "reusing active challenge" note in that
	// case instead of implying rotation.
	Reused bool `json:"reused,omitempty"`
	// Rotated is true when the server revoked a prior active token to
	// mint this one (only when the request set force=true, status 201).
	// The CLI prints a loud "previous token revoked — update your DNS"
	// warning so the operator notices their existing TXT is now stale.
	Rotated bool `json:"rotated,omitempty"`
}

HostnameChallenge mirrors a fresh challenge row + its operator- facing instructions string.

type HostnameStatus

type HostnameStatus struct {
	Hostname
	ActiveChallenges []HostnameStatusChallenge `json:"active_challenges,omitempty"`
}

HostnameStatus is the read-only state-of-the-hostname view returned by GET /hostnames/{hostname}/status. Lets the CLI show the current verify token (and verified state) WITHOUT mutating anything — pre-status, the only way to "see" the token was to call challenge, which rotated it (internal docs/todo-custom-domains.md §6a).

type HostnameStatusChallenge

type HostnameStatusChallenge struct {
	ID           string `json:"id"`
	Method       string `json:"method"`
	Token        string `json:"token"`
	ExpiresAt    string `json:"expires_at"`
	Expired      bool   `json:"expired,omitempty"`
	AttemptedAt  string `json:"attempted_at,omitempty"`
	LastError    string `json:"last_error,omitempty"`
	Instructions string `json:"instructions,omitempty"`
}

HostnameStatusChallenge is one entry of HostnameStatus.ActiveChallenges — same shape as HostnameChallenge minus the issuance-only Reused / Rotated flags, plus diagnostic fields (expired, last error from the previous verify attempt).

type HostnameVerifyResponse

type HostnameVerifyResponse struct {
	VerifiedAt string `json:"verified_at"`
	Method     string `json:"method"`
}

HostnameVerifyResponse mirrors the /verify endpoint's success body.

type Invitation

type Invitation struct {
	InvitationID string   `json:"invitation_id"`
	Label        string   `json:"label,omitempty"`
	Kind         string   `json:"kind,omitempty"`
	Capabilities []string `json:"capabilities"`
	CreatedBy    string   `json:"created_by"`
	CreatedAt    string   `json:"created_at"`
	ExpiresAt    string   `json:"expires_at"`
	ConsumedAt   *string  `json:"consumed_at,omitempty"`
	ConsumedBy   string   `json:"consumed_by,omitempty"`
	RevokedAt    *string  `json:"revoked_at,omitempty"`
	Status       string   `json:"status"`
}

Invitation mirrors the server's invitation row for listing.

type ListResponse

type ListResponse struct {
	Ops []Op `json:"ops"`
}

type NetworkError

type NetworkError struct {
	Msg   string
	Cause error
}

NetworkError is the user-facing wrapping prettifyNetworkError uses when it recognises a transport-layer failure. Error() returns just the friendly sentence — the raw `Post "http://…": dial tcp …` text is hidden from `%v` output but still reachable via errors.Unwrap (and therefore errors.Is on syscall.ECONNREFUSED, net.DNSError, etc.). Debuggers grep the wrap chain; operators read the message.

func (*NetworkError) Error

func (e *NetworkError) Error() string

func (*NetworkError) Unwrap

func (e *NetworkError) Unwrap() error

type Op

type Op struct {
	Stack   string `json:"stack"`
	Scope   int    `json:"scope"`
	Name    string `json:"name"`
	Txcl    string `json:"txcl"`
	MockReq string `json:"mock_req,omitempty"`
	MockRes string `json:"mock_res,omitempty"`
}

Op mirrors the wire shape used by chassis/server/admin.OpRecord. Kept duplicated rather than imported so the CLI doesn't pull in the server package transitively.

type PatchFileResponse

type PatchFileResponse struct {
	Path         string `json:"path"`
	ContentHash  string `json:"content_hash"`
	ManifestHash string `json:"manifest_hash"`
}

type PutFilesResponse

type PutFilesResponse struct {
	ManifestHash string `json:"manifest_hash"`
}

type RevokeInvitationResponse

type RevokeInvitationResponse struct {
	Revoked      bool   `json:"revoked"`
	InvitationID string `json:"invitation_id"`
}

RevokeInvitationResponse mirrors the server's revoke response shape.

type RevokeResponse

type RevokeResponse struct {
	Revoked bool   `json:"revoked"`
	ActorID string `json:"actor_id,omitempty"`
	KeyID   string `json:"key_id,omitempty"`
}

RevokeResponse mirrors chassis/server/admin.revokeResponse.

type Secret

type Secret struct {
	SecretID      string `json:"secret_id"`
	TenantID      string `json:"tenant_id"`
	Stack         string `json:"stack,omitempty"`
	Name          string `json:"name"`
	Description   string `json:"description,omitempty"`
	CreatedAt     string `json:"created_at"`
	CreatedBy     string `json:"created_by,omitempty"`
	LastRotatedAt string `json:"last_rotated_at,omitempty"`
	KeyVersion    int    `json:"key_version"`
	VersionNo     int    `json:"version_no"`
}

Secret is the metadata view of a tenant_secrets row. NEVER contains a value field — the only paths that return cleartext are GenerateSecret and RotateSecretGenerated, both via SecretWithValue.

type SecretWithValue

type SecretWithValue struct {
	Secret Secret `json:"secret"`
	Value  string `json:"value"`
}

SecretWithValue is the response shape from GenerateSecret and RotateSecretGenerated — the only two paths that return cleartext. `Value` is base64-url no-padding encoded random bytes.

type SessionRecord

type SessionRecord struct {
	SessionID  string  `json:"session_id"`
	ActorID    string  `json:"actor_id"`
	TenantID   string  `json:"tenant_id"`
	UA         string  `json:"ua,omitempty"`
	IP         string  `json:"ip,omitempty"`
	CreatedAt  string  `json:"created_at"`
	ExpiresAt  string  `json:"expires_at"`
	LastSeenAt string  `json:"last_seen_at"`
	RevokedAt  *string `json:"revoked_at,omitempty"`
	RevokedBy  string  `json:"revoked_by,omitempty"`
}

SessionRecord mirrors the chassis's sessionRecord; one entry in the list-sessions response or the read side of a future "manage sessions" view.

type StackFile

type StackFile struct {
	Path        string `json:"path"`
	Content     string `json:"content,omitempty"`
	ContentHash string `json:"content_hash"`
}

type StackRecord

type StackRecord struct {
	Name          string `json:"name"`
	ActiveVersion *int64 `json:"active_version,omitempty"`
	CreatedAt     string `json:"created_at"`
}

type Target

type Target struct {
	Addr   string
	User   string
	Pass   string
	Tenant string
	Auth   signer.Signer
}

Target is the destination chassis — URL plus optional basic auth. When Auth is non-nil, signed requests take precedence over basic.

Auth holds a signer.Signer (interface), not a concrete struct, so the chosen backend (file key, ssh-agent, future hardware) plugs in at this seam without the client knowing which it talks to.

Tenant is the slug under which tenant-scoped requests are issued. Empty means "talk to the legacy flat routes" — useful for chassis-wide endpoints (whoami, key revoke) where there's no tenant context, and for callers that haven't migrated yet. Phase 2 keeps both URL shapes wired on the server.

type Tenant

type Tenant struct {
	TenantID  string `json:"tenant_id"`
	Slug      string `json:"slug"`
	Name      string `json:"name,omitempty"`
	CreatedAt string `json:"created_at"`
}

Tenant mirrors the server's tenant row for listing.

type TenantMember

type TenantMember struct {
	ActorID      string   `json:"actor_id"`
	Label        string   `json:"label,omitempty"`
	Capabilities []string `json:"capabilities"`
	CreatedAt    string   `json:"created_at"`
}

TenantMember is one row of GET /v1/tenants/{t}/auth/members.

type TraceListResponse

type TraceListResponse struct {
	Traces []TraceSummary `json:"traces"`
	Total  int            `json:"total"`
}

TraceListResponse mirrors chassis/server/admin.traceListResponse — a paginated list of recent traces returned by GET /traces/requests.json.

type TraceNotFoundError

type TraceNotFoundError struct{ RID string }

TraceNotFoundError marks a 404 from the trace endpoint so the caller can produce a friendly "no trace for rid …" message instead of the raw HTTP error.

func (*TraceNotFoundError) Error

func (e *TraceNotFoundError) Error() string

type TraceResponse

type TraceResponse struct {
	RID    string `json:"rid"`
	Src    string `json:"src,omitempty"`
	Tenant string `json:"tenant,omitempty"`
	// Stack is the boot trampoline; Route is the first stage.jump's
	// destination. See TraceSummary for the rationale.
	Stack            string         `json:"stack,omitempty"`
	Route            string         `json:"route,omitempty"`
	StartedAt        string         `json:"started_at,omitempty"`
	FinishedAt       string         `json:"finished_at,omitempty"`
	DurationMs       *int64         `json:"duration_ms,omitempty"`
	Status           string         `json:"status"`
	PayloadBytes     int64          `json:"payload_bytes,omitempty"`
	PayloadTruncated bool           `json:"payload_truncated,omitempty"`
	TraceMode        string         `json:"trace_mode,omitempty"`
	Steps            []TraceStep    `json:"steps"`
	In               map[string]any `json:"in,omitempty"`
	Out              any            `json:"out,omitempty"`
}

TraceResponse mirrors chassis/server/admin.traceRequestResponse — the aggregated view of one request returned by GET /traces/requests/{rid}.json.

type TraceStep

type TraceStep struct {
	Name            string `json:"name"`
	Operation       string `json:"operation,omitempty"`
	Transport       string `json:"transport,omitempty"`
	Stack           string `json:"stack,omitempty"`
	Scope           int    `json:"scope"`
	StartedAt       string `json:"started_at,omitempty"`
	FinishedAt      string `json:"finished_at,omitempty"`
	DurationMs      int64  `json:"duration_ms"`
	Status          string `json:"status"`
	InputBytes      int64  `json:"input_bytes"`
	OutputBytes     int64  `json:"output_bytes"`
	InputTruncated  bool   `json:"input_truncated,omitempty"`
	OutputTruncated bool   `json:"output_truncated,omitempty"`
	Error           string `json:"error,omitempty"`
	In              any    `json:"in,omitempty"`
	Out             any    `json:"out,omitempty"`
}

type TraceSummary

type TraceSummary struct {
	RID    string `json:"rid"`
	Src    string `json:"src,omitempty"`
	Tenant string `json:"tenant,omitempty"`
	// Stack is the chassis trampoline stack the request enters at
	// (typically "boot/%/0"). Route is the destination of the first
	// stage.jump, if any — much more useful than Stack since every
	// request enters at the same trampoline.
	Stack      string `json:"stack,omitempty"`
	Route      string `json:"route,omitempty"`
	StartedAt  string `json:"started_at,omitempty"`
	FinishedAt string `json:"finished_at,omitempty"`
	DurationMs *int64 `json:"duration_ms,omitempty"`
	Status     string `json:"status"`
}

TraceSummary is the per-trace summary used in the list view.

type ValidateError

type ValidateError struct {
	Path string `json:"path"`
	Err  string `json:"err"`
}

type ValidateResponse

type ValidateResponse struct {
	OK      bool            `json:"ok"`
	Errors  []ValidateError `json:"errors,omitempty"`
	Checked int             `json:"checked"`
}

type VersionDetail

type VersionDetail struct {
	VersionRecord
	Files []StackFile `json:"files"`
}

type VersionRecord

type VersionRecord struct {
	VersionNumber int64   `json:"version_number"`
	Status        string  `json:"status"`
	ParentVersion *int64  `json:"parent_version_number,omitempty"`
	CreatedBy     string  `json:"created_by"`
	CreatedAt     string  `json:"created_at"`
	ActivatedAt   *string `json:"activated_at,omitempty"`
	ManifestHash  string  `json:"manifest_hash"`
	IsActive      bool    `json:"is_active"`
}

type WhoamiMembership

type WhoamiMembership struct {
	TenantID     string   `json:"tenant_id"`
	TenantSlug   string   `json:"tenant_slug"`
	Capabilities []string `json:"capabilities"`
}

WhoamiMembership is one row of the per-tenant grants for the caller, returned alongside identity.

type WhoamiResponse

type WhoamiResponse struct {
	Source       string             `json:"source"`
	ActorID      string             `json:"actor_id,omitempty"`
	KeyID        string             `json:"key_id,omitempty"`
	Label        string             `json:"label,omitempty"`
	SuperAdmin   bool               `json:"super_admin,omitempty"`
	Capabilities []string           `json:"capabilities"`
	Memberships  []WhoamiMembership `json:"memberships,omitempty"`
}

WhoamiResponse mirrors chassis/server/admin.whoamiResponse.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL