capture

package
v0.6.2 Latest Latest
Warning

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

Go to latest
Published: Jun 29, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package capture builds and uploads context-sync session captures. It owns the wire contract for POST /api/v1/contexts/sessions, the canonical content hash, the non-interactive capture credential, and the ingest client.

Index

Constants

View Source
const IngestPath = "/api/v1/contexts/sessions"

IngestPath is the canonical v1 ingest endpoint.

Variables

This section is empty.

Functions

func CredentialPath

func CredentialPath(workspace string) (string, error)

CredentialPath returns the 0600 env file path for a workspace's capture key.

func SaveCredential

func SaveCredential(workspace string, cred Credential) (string, error)

SaveCredential writes the capture credential for a workspace, creating the 0700 dir and a 0600 env file the hook can source.

Types

type Credential

type Credential struct {
	PublicKey string
	SecretKey string
}

Credential is the workspace-bound, least-privilege capture key the detached hook uses. It is NEVER the OS keychain (DX-3): a detached background process cannot reliably unlock the keychain, so `sync init` mints this key and stores it as a 0600 file in a 0700 per-user dir that `sync run` reads directly.

func LoadCredential

func LoadCredential(workspace string) (*Credential, error)

LoadCredential reads a workspace's capture credential. A missing file returns (nil, nil) so `sync run` can degrade to spooling rather than failing.

type IngestRequest

type IngestRequest struct {
	WorkspaceID     string   `json:"workspaceId"`
	DirectoryID     string   `json:"directoryId,omitempty"`
	ClaudeSessionID string   `json:"claudeSessionId"`
	Source          string   `json:"source"`
	CaptureMode     Mode     `json:"captureMode"`
	Summary         string   `json:"summary,omitempty"`
	Metadata        Metadata `json:"metadata"`
	ContentHash     string   `json:"contentHash"`
	OccurredAt      string   `json:"occurredAt"`
	// RedactionApplied records whether client-side redaction actually replaced
	// any secret span in this capture (provenance for the governance UI).
	RedactionApplied bool `json:"redactionApplied"`
	// LowSignal is a top-level governance routing hint (FR-Q4): true when the
	// session has no real user turn and no tool work. The backend maps it to
	// governance_status='low_signal' so it is excluded from the default inbox.
	// It is deliberately a sibling of summary/occurredAt — NOT under metadata —
	// and is excluded from the canonical content hash so it never perturbs dedup.
	LowSignal bool `json:"lowSignal,omitempty"`
}

IngestRequest is the POST /api/v1/contexts/sessions body. Field names match the canonical v1 contract exactly.

func (*IngestRequest) ComputeContentHash

func (r *IngestRequest) ComputeContentHash() string

ComputeContentHash computes the canonical content hash for idempotency. The server recomputes and validates this (SEC-9: a client hash is advisory), but the CLI sends a matching value so retries dedupe deterministically.

The hash covers the semantic content (session id, source, mode, summary, metadata) and deliberately excludes occurredAt so a re-run of the same session produces the same hash.

type IngestResponse

type IngestResponse struct {
	Status           string `json:"status"`
	CaptureID        string `json:"captureId"`
	FileID           string `json:"fileId"`
	VersionID        string `json:"versionId"`
	GovernanceStatus string `json:"governanceStatus"`
}

IngestResponse is the server reply. Status is one of accepted | deduped | superseded | disabled_by_policy | excluded.

func Ingest

func Ingest(p Poster, req *IngestRequest) (*IngestResponse, error)

Ingest POSTs a capture to the backend and returns the parsed response. It fills the canonical ContentHash before sending if the caller left it empty.

type Metadata

type Metadata struct {
	RepoURL      string   `json:"repoUrl,omitempty"`
	Branch       string   `json:"branch,omitempty"`
	HeadSha      string   `json:"headSha,omitempty"`
	FilesTouched []string `json:"filesTouched,omitempty"`
	Commands     []string `json:"commands,omitempty"`
	Outcome      string   `json:"outcome,omitempty"`

	// Semantic identity fields (FR-1/FR-5/FR-7). All sanitized + redacted before
	// assignment. The server persists Title→captures.title, Description→
	// captures.description, TaskAtHand→captures.first_prompt, ProjectKey→
	// captures.project_key, RepoSlug→captures.repo_slug, and prefers these over
	// its own distillation when present.
	Title       string `json:"title,omitempty"`
	Description string `json:"description,omitempty"`
	TaskAtHand  string `json:"taskAtHand,omitempty"`
	ProjectKey  string `json:"projectKey,omitempty"`
	RepoSlug    string `json:"repoSlug,omitempty"`
}

Metadata is the structural provenance block sent with every capture. Field names are camelCase to match the canonical v1 wire contract.

type Mode

type Mode string

Mode is the capture granularity.

const (
	ModeSummary    Mode = "summary"
	ModeMetadata   Mode = "metadata"
	ModeTranscript Mode = "transcript"
)

type Poster

type Poster interface {
	Post(path string, body interface{}, result interface{}) error
}

Poster is the minimal HTTP surface the ingest client needs. *api.Caller satisfies it; tests provide a fake.

Jump to

Keyboard shortcuts

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