clicore

package module
v0.8.0 Latest Latest
Warning

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

Go to latest
Published: Jul 23, 2026 License: MIT Imports: 30 Imported by: 0

README

Share2Us CLI Core

The shared Go library behind the Share2Us CLI. It holds the logic the command-line client is built on: the API client, credential storage, end-to-end crypto, QR rendering, local secret scanning, device identification, and the offline LAN / P2P transfer stack.

This module is published so the CLI builds from source and so the pieces can be reused, but its primary consumer is the CLI. If you just want the tool, start at share2us/cli.

Install

Requires Go 1.25+.

go get github.com/share2us/cli-core@latest

What's inside

Area Files What it does
API client client.go, core.go Talks to the Share2Us API; usage/version strings.
Config & credentials config.go, credentials.go, localshare_config.go Base-URL resolution, upload defaults, saved logins.
Crypto crypto.go End-to-end encryption for device/contact sends.
QR qr.go Renders content and share links as terminal QR codes.
Secret scan secretscan.go Local gitleaks-style scan run before uploads.
Content class contentclass.go Classifies input (text vs binary, size limits) for QR/live decisions.
Devices device*.go Per-OS device identification (Linux/macOS/Windows).
Offline transfer lanshare/ Direct LAN/Tailscale/WireGuard transfer (TLS 1.3 + PAKE, mDNS).
P2P p2p/ WebRTC peer-to-peer streaming (build-gated).
Self-update browser.go, pending_reseal.go, tips.go, cache.go Update flow, browser launch, cached state, CLI tips.

Versioning

The module is tagged (v0.1.0, v0.2.0, …). Its API tracks what the CLI needs rather than promising a stable public surface, so pin a version if you depend on it directly.

Contributing

See CONTRIBUTING.md. Most user-facing behavior is exercised through the CLI; changes here should keep it building and green.

License

MIT © Share2Us

Documentation

Index

Constants

View Source
const (
	APIBaseSourceEnv     = "env"
	APIBaseSourceConfig  = "config"
	APIBaseSourceDefault = "default"
)
View Source
const (
	DefaultBaseURL   = "share2.us"
	DefaultAPIBase   = "https://api.share2.us"
	DefaultShareBase = "https://s.share2.us"
)
View Source
const APITokenEnv = "SHARE2US_API_TOKEN"

APITokenEnv is the environment variable a caller (CI, automation) can set to authenticate with a personal access token instead of an interactive login.

View Source
const APITokenPrefix = "s2u_pat_"

APITokenPrefix marks a Share2Us personal access token (PAT) on the wire. Mirrors the server-side prefix; used to recognise env-provided tokens.

View Source
const ContentClassFolder = "folder"
View Source
const CredentialSchemaVersion = 1
View Source
const DefaultSecretScanMaxBytes int64 = 5 * 1024 * 1024
View Source
const (
	EncryptionAlgoAES256GCM = "aes256gcm"
)
View Source
const PendingResealTTL = 14 * 24 * time.Hour
View Source
const QRContentMaxBytes = 1000

QRContentMaxBytes caps an in-terminal *content* QR so it stays scannable by a phone camera. It is far below the raw QR byte-mode ceiling (2953 bytes / a 177x177-module code): a terminal renders each module ~one character cell, so a dense high-version code can't be resolved from a screen. Tunable.

View Source
const QRContentWarnBytes = 300

QRContentWarnBytes: above this (but under the hard cap) a content QR still encodes, but the code is dense enough that it may be harder to scan.

Variables

View Source
var (
	BuildVersion = "dev"
	Version      = "dev"

	// P2PEnabled gates the direct peer-to-peer streaming commands (`p2p send/recv`
	// and the `stream` alias). Build-time flag, set with:
	//
	//   -ldflags "-X github.com/share2us/cli-core.P2PEnabled=true"
	//
	// It DEFAULTS OFF and is fail-safe: any value other than "true" disables the
	// commands and hides them from the usage text. P2P is also gated server-side
	// (SHARE2US_P2P_ENABLED + the p2p_streaming_enabled plan entitlement), so this
	// is a shipping switch, not a security control — a rebuilt binary cannot turn
	// the feature on by itself.
	P2PEnabled = "false"
)
View Source
var DefaultHTTPClient = &http.Client{
	Transport: &http.Transport{
		Proxy:                 http.ProxyFromEnvironment,
		DialContext:           (&net.Dialer{Timeout: 15 * time.Second, KeepAlive: 30 * time.Second}).DialContext,
		ForceAttemptHTTP2:     true,
		MaxIdleConns:          100,
		IdleConnTimeout:       90 * time.Second,
		TLSHandshakeTimeout:   10 * time.Second,
		ResponseHeaderTimeout: 30 * time.Second,
		ExpectContinueTimeout: 1 * time.Second,
	},
}

DefaultHTTPClient bounds connection setup and slow-header responses so a slow or malicious server (including a presigned-URL host) cannot pin the CLI during setup. It deliberately sets no overall Timeout: file up/downloads can be long, and the per-request context is what bounds total call duration.

View Source
var (
	ErrInvalidKey = errors.New("invalid encryption key")
)

Functions

func APIBaseFromBaseURL

func APIBaseFromBaseURL(baseURL string) (string, error)

func CacheBaseDir

func CacheBaseDir() (string, error)

func CacheEntryIsLocal

func CacheEntryIsLocal(entry CacheEntry) bool

func CacheManifestPath

func CacheManifestPath() (string, error)

func CacheObjectsDir

func CacheObjectsDir() (string, error)

func ConfigPath

func ConfigPath() (string, error)

func ContentClassForNameAndType

func ContentClassForNameAndType(name, contentType string) string

func CredentialPath

func CredentialPath() (string, error)

CredentialPath is where the CLI stores its saved login. It mirrors ConfigPath (os.UserConfigDir) so the token and config.json live together: ~/.config/share2us on Linux/macOS (honoring XDG_CONFIG_HOME) and %AppData%\Roaming\share2us on Windows. Before 2026-07 this used XDG/HOME directly, which on Windows put the token under %USERPROFILE%\.config instead — see legacyCredentialPath.

func DecodeKey

func DecodeKey(encoded string) ([]byte, error)

func DecryptStream

func DecryptStream(dst io.Writer, src io.Reader, key []byte) error

func DefaultExpiry

func DefaultExpiry() string

func DeleteCredential

func DeleteCredential() error

func DownloadGatewayURL

func DownloadGatewayURL(apiBase, publicID string) (string, error)

func DurationForAPI

func DurationForAPI(value string) (string, error)

func EncodeKey

func EncodeKey(key []byte) string

func EncryptStream

func EncryptStream(dst io.Writer, src io.Reader, key []byte) error

func EnvAPIToken

func EnvAPIToken() string

EnvAPIToken returns the trimmed value of SHARE2US_API_TOKEN, or "" if unset. When non-empty it takes precedence over the on-disk device credential.

func ExpiryForAPI added in v0.4.0

func ExpiryForAPI(value string) (expiresIn string, noExpiry bool, err error)

ExpiryForAPI translates a user-supplied expiry value into the wire fields for the upload/reshare API. "0", "none", "never", "keep", and "forever" mean the share is kept indefinitely (no expiry): noExpiry=true with an empty duration. Anything else is validated as a positive finite duration via DurationForAPI.

func FileSHA256

func FileSHA256(path string) (string, error)

func ForgetRetainedKey

func ForgetRetainedKey(sharePublicID string) error

ForgetRetainedKey drops a retained content key once its share has been delivered.

func FullVersion

func FullVersion() string

func IsAPIToken

func IsAPIToken(token string) bool

IsAPIToken reports whether token is a personal access token. PATs carry no device identity, so device end-to-end features are unavailable with one.

func IsAuthorizationPending

func IsAuthorizationPending(err error) bool

func IsDeviceLimitReached

func IsDeviceLimitReached(err error) bool

func IsHighConfidenceSecretRule

func IsHighConfidenceSecretRule(ruleID string) bool

IsHighConfidenceSecretRule reports whether a gitleaks rule ID denotes a high-confidence secret. This is the concrete definition of "high confidence" used to hard-block agent uploads.

func KeyFromShareURL

func KeyFromShareURL(raw string) ([]byte, error)

func ListIndexPath

func ListIndexPath() (string, error)

func NewDataKey

func NewDataKey() ([]byte, error)

func NewInstallID

func NewInstallID() string

NewInstallID returns a random anonymous install id.

func NormalizeAPIHost

func NormalizeAPIHost(value string) (string, error)

func NormalizeBaseURL

func NormalizeBaseURL(value string) (string, error)

func NormalizeShareBase

func NormalizeShareBase(value string) (string, error)

func OpenBrowser

func OpenBrowser(rawURL string) error

func OpenSealedContentKey

func OpenSealedContentKey(sealedKey, publicKey, privateKey string) ([]byte, error)

func P2PStreamingEnabled

func P2PStreamingEnabled() bool

P2PStreamingEnabled reports whether this build exposes the P2P commands.

func ParseDuration

func ParseDuration(value string) (time.Duration, error)

func PendingResealPath

func PendingResealPath() (string, error)

func QRIsText

func QRIsText(b []byte) bool

QRIsText reports whether b is safe to embed as QR text — valid UTF-8 with no NUL bytes (the same heuristic used to gate --live text streaming).

func RandomTip

func RandomTip(command string) string

RandomTip returns a single random tip for the command (or "" if none).

func RedactSecretFinding

func RedactSecretFinding(match, secret string) string

func RenderQR

func RenderQR(content string) (string, error)

RenderQR returns a QR code of content drawn with Unicode half-blocks (two modules per character row) at error-correction level M, with a quiet-zone border. It errors only if content exceeds the absolute QR capacity; callers should enforce QRContentMaxBytes first for scannability.

func ResolveAPIBase

func ResolveAPIBase() (string, string, error)

func ResolveBaseURL

func ResolveBaseURL() (string, string, error)

func ResolveShareBase

func ResolveShareBase() (string, string, error)

func RetainContentKey

func RetainContentKey(sharePublicID, contentKeyB64, recipientEmail string) error

RetainContentKey records a content key so the share can be re-sealed later. A best-effort helper: a store error is returned but callers may choose to warn-and-continue rather than fail the send (retention is a recovery aid, not core to delivery).

func SaveCacheManifest

func SaveCacheManifest(manifest CacheManifest) error

func SaveCacheManifestAt

func SaveCacheManifestAt(path string, manifest CacheManifest) error

func SaveConfig

func SaveConfig(config Config) error

func SaveConfigAt

func SaveConfigAt(path string, config Config) error

func SaveCredential

func SaveCredential(credential Credential) error

func SaveCredentialAt

func SaveCredentialAt(path string, credential Credential) error

func SaveListIndex

func SaveListIndex(entries []ListIndexEntry) error

func SaveListIndexAt

func SaveListIndexAt(path string, entries []ListIndexEntry) error

func SavePendingReseal

func SavePendingReseal(store PendingResealStore) error

func SaveSourceRegistry

func SaveSourceRegistry(registry SourceRegistry) error

func SaveSourceRegistryAt

func SaveSourceRegistryAt(path string, registry SourceRegistry) error

func SaveUpdateCheckCache

func SaveUpdateCheckCache(cache UpdateCheckCache) error

func SaveUpdateCheckCacheAt

func SaveUpdateCheckCacheAt(path string, cache UpdateCheckCache) error

func SealContentKeyForDevice

func SealContentKeyForDevice(contentKey []byte, targetPublicKey string) (string, error)

func SecretFindingsError

func SecretFindingsError(count int) error

func ShareBaseFromBaseURL

func ShareBaseFromBaseURL(baseURL string) (string, error)

func ShareURLWithKey

func ShareURLWithKey(base, publicID string, key []byte) string

func SleepInterval

func SleepInterval(interval int) time.Duration

func SourceRefForPath

func SourceRefForPath(path string) (string, string, error)

func SourceRegistryPath

func SourceRegistryPath() (string, error)

func Tips

func Tips(command string) []string

Tips returns the tip lines rendered for the given command name.

func UpdateCheckCachePath

func UpdateCheckCachePath() (string, error)

func Usage

func Usage(command string) string

func VerificationURL

func VerificationURL(code DeviceCodeResponse) string

Types

type APIError

type APIError struct {
	Status      int
	Code        string
	Message     string
	RequestID   string
	DeviceLimit *DeviceLimitDetails
}

func (*APIError) Error

func (e *APIError) Error() string

type APITokenInfo

type APITokenInfo struct {
	ID        string   `json:"id"`
	Label     string   `json:"label"`
	Scopes    []string `json:"scopes"`
	TokenHint string   `json:"token_hint"`
	ExpiresAt string   `json:"expires_at,omitempty"`
}

APITokenInfo is the non-secret metadata of a personal API token.

type AccessControlsRequest

type AccessControlsRequest struct {
	MaxViews       uint64   `json:"max_views"`
	AllowedDomains []string `json:"allowed_domains"`
	DeniedDomains  []string `json:"denied_domains"`
}

type AnalyticsTimelinePoint

type AnalyticsTimelinePoint struct {
	Date      string `json:"date"`
	Views     uint64 `json:"views"`
	Downloads uint64 `json:"downloads"`
}

type CacheEntry

type CacheEntry struct {
	Path      string    `json:"path"`
	SizeBytes uint64    `json:"size_bytes"`
	SHA256    string    `json:"sha256"`
	FileName  string    `json:"file_name"`
	PulledAt  time.Time `json:"pulled_at"`
}

type CacheManifest

type CacheManifest map[string]CacheEntry

func AddCacheEntry

func AddCacheEntry(manifest CacheManifest, publicID string, entry CacheEntry) CacheManifest

func LoadCacheManifest

func LoadCacheManifest() (CacheManifest, error)

func LoadCacheManifestAt

func LoadCacheManifestAt(path string) (CacheManifest, error)

func RemoveCacheEntry

func RemoveCacheEntry(manifest CacheManifest, publicID string) CacheManifest

type Client

type Client struct {
	BaseURL    string
	Token      string
	HTTPClient *http.Client
}

func NewClient

func NewClient(apiBase, token string) *Client

func (*Client) AckInboxShare

func (c *Client) AckInboxShare(ctx context.Context, publicID string) error

AckInboxShare tells the server a received share was delivered to this device, so it stops flagging the share for re-seal and the sender can prune its retained content key.

func (*Client) ApprovePendingInbox

func (c *Client) ApprovePendingInbox(ctx context.Context, publicID string) error

func (*Client) AuthorizeP2PRoom

func (c *Client) AuthorizeP2PRoom(ctx context.Context, room, role string) (P2PRoomAuth, error)

AuthorizeP2PRoom asks the API for permission to create ("send") or join ("recv") a relay room. The room is only the PUBLIC half of the pairing code — the secret half never leaves this machine.

func (*Client) CheckUpdate

func (c *Client) CheckUpdate(ctx context.Context, version, osName, arch string) (UpdateCheckResponse, error)

func (*Client) CompleteUpload

func (c *Client) CompleteUpload(ctx context.Context, uploadSessionID string) (UploadCompleteResponse, error)

func (*Client) CreateAPIToken

func (c *Client) CreateAPIToken(ctx context.Context, label string, scopes []string, expiresInDays *int) (CreateAPITokenResponse, error)

CreateAPIToken mints a scoped personal API token (ADR-015). Session-only on the server, so the caller must be an interactive login, not another PAT. Pass expiresInDays=nil for no expiry, or a positive day count.

func (*Client) CreateReplaceUpload

func (c *Client) CreateReplaceUpload(ctx context.Context, publicID string, upload UploadCreateRequest) (UploadCreateResponse, error)

func (*Client) CreateUpload

func (c *Client) CreateUpload(ctx context.Context, upload UploadCreateRequest) (UploadCreateResponse, error)

func (*Client) DeleteShare

func (c *Client) DeleteShare(ctx context.Context, publicID string) error

func (*Client) DeleteTeammateSender

func (c *Client) DeleteTeammateSender(ctx context.Context, email string) error

func (*Client) DisableShare

func (c *Client) DisableShare(ctx context.Context, publicID string) (Share, error)

func (*Client) DownloadInboxContent

func (c *Client) DownloadInboxContent(ctx context.Context, publicID string, dst io.Writer) error

func (*Client) DownloadURL

func (c *Client) DownloadURL(ctx context.Context, rawURL string, dst io.Writer) error

func (*Client) EnableShare

func (c *Client) EnableShare(ctx context.Context, publicID string) (Share, error)

func (*Client) ExposeDeviceToContact added in v0.5.0

func (c *Client) ExposeDeviceToContact(ctx context.Context, email, deviceSessionID string) error

ExposeDeviceToContact allows the given contact (by email) to target one of the caller's own devices under the 'approvals' inbound mode.

func (*Client) ExtendExpiry

func (c *Client) ExtendExpiry(ctx context.Context, publicID string, expiresIn time.Duration) (Share, error)

func (*Client) FlushShare

func (c *Client) FlushShare(ctx context.Context, publicID string) (LiveFlushResponse, error)

func (*Client) GetOnboarding

func (c *Client) GetOnboarding(ctx context.Context) (OnboardingStatus, error)

func (*Client) GetShare

func (c *Client) GetShare(ctx context.Context, publicID string) (Share, error)

func (*Client) GetTeammatePolicy

func (c *Client) GetTeammatePolicy(ctx context.Context) (TeammatePolicy, error)

func (*Client) Inbox

func (c *Client) Inbox(ctx context.Context) (InboxResponse, error)

func (*Client) ListDevices

func (c *Client) ListDevices(ctx context.Context) (ListDevicesResponse, error)

func (*Client) ListExposedDevicesForContact added in v0.5.0

func (c *Client) ListExposedDevicesForContact(ctx context.Context, email string) ([]string, error)

ListExposedDevicesForContact returns the caller's device session ids currently exposed to the given contact.

func (*Client) ListPendingInbox

func (c *Client) ListPendingInbox(ctx context.Context) (PendingInboxResponse, error)

func (*Client) ListShares

func (c *Client) ListShares(ctx context.Context) (ListSharesResponse, error)

func (*Client) Logout

func (c *Client) Logout(ctx context.Context) error

func (*Client) Me

func (c *Client) Me(ctx context.Context) (MeResponse, error)

func (*Client) PollDeviceToken

func (c *Client) PollDeviceToken(ctx context.Context, deviceCode string) (DeviceTokenResponse, error)

func (*Client) PutLive

func (c *Client) PutLive(ctx context.Context, publicID string, request LivePutRequest) (LivePutResponse, error)

func (*Client) PutUpload

func (c *Client) PutUpload(ctx context.Context, upload PresignedUpload, body io.Reader, size int64) error

func (*Client) RegisterDeviceKey

func (c *Client) RegisterDeviceKey(ctx context.Context, publicKey string) error

func (*Client) RejectPendingInbox

func (c *Client) RejectPendingInbox(ctx context.Context, publicID string) error

func (*Client) ReportInstall

func (c *Client) ReportInstall(ctx context.Context, e InstallEvent) error

ReportInstall posts an anonymous install/update ping (unauthenticated).

func (*Client) ResealQueue

func (c *Client) ResealQueue(ctx context.Context) (ResealQueueResponse, error)

ResealQueue lists in-flight shares the caller sent that need re-sealing to a recipient's new device key.

func (*Client) RevokeAllShares

func (c *Client) RevokeAllShares(ctx context.Context) (RevokeAllResponse, error)

func (*Client) RevokeDeviceSession

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

func (*Client) RevokeDeviceSessionWithDeviceCode

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

func (*Client) RevokeShare

func (c *Client) RevokeShare(ctx context.Context, publicID string) (Share, error)

func (*Client) SetTeammatePolicy

func (c *Client) SetTeammatePolicy(ctx context.Context, mode string) error

func (*Client) SetTeammateSender

func (c *Client) SetTeammateSender(ctx context.Context, email, mode string) error

func (*Client) ShareAnalytics

func (c *Client) ShareAnalytics(ctx context.Context, publicID string) (ShareAnalyticsResponse, error)

func (*Client) StartDeviceCode

func (c *Client) StartDeviceCode(ctx context.Context, request ...DeviceCodeRequest) (DeviceCodeResponse, error)

func (*Client) SubmitConsent

func (c *Client) SubmitConsent(ctx context.Context, version string) error

SubmitConsent records acceptance of the given terms/data-share version.

func (*Client) SubmitReseal

func (c *Client) SubmitReseal(ctx context.Context, publicID, targetSessionID, sealedKey string) error

SubmitReseal uploads a content key re-sealed to a recipient's new device public key.

func (*Client) TeammateDevices

func (c *Client) TeammateDevices(ctx context.Context, email string) (TeammateDeviceList, error)

TeammateDevices fetches the recipient's registered device public keys (the release gate); a disallowed policy returns an APIError with code "recipient_not_accepting"; an unregistered recipient returns Code "recipient_not_registered" with no devices.

func (*Client) UnexposeDeviceFromContact added in v0.5.0

func (c *Client) UnexposeDeviceFromContact(ctx context.Context, email, deviceSessionID string) error

UnexposeDeviceFromContact revokes a contact's access to one of the caller's devices.

func (*Client) UpdateAccessControls

func (c *Client) UpdateAccessControls(ctx context.Context, publicID string, controls AccessControlsRequest) (Share, error)

func (*Client) Usage

func (c *Client) Usage(ctx context.Context) (UsageResponse, error)

type Config

type Config struct {
	BaseURL   string `json:"base_url,omitempty"`
	Host      string `json:"host,omitempty"`
	ShareBase string `json:"share_base,omitempty"`
	MachineID string `json:"machine_id,omitempty"`
	// InstallID is a random, anonymous id generated once on first run and used
	// only for install counting (todo §J.4). Not tied to the account.
	InstallID string `json:"install_id,omitempty"`
	// InstallReported is set once the one-time install ping has been attempted.
	InstallReported bool `json:"install_reported,omitempty"`
	// Reshare is the LEGACY standing reshare default (ADR-024). Superseded by
	// Defaults.Reshare (O-C1); still read for back-compat. nil = unset.
	Reshare *bool `json:"reshare,omitempty"`
	// Defaults are standing per-user defaults for SAFE upload options (O-C1). Only
	// options that can't silently over-expose are defaultable here; an explicit flag
	// always overrides. Footgun options (password, one-time, recipients, visibility,
	// allow-secrets, device/contact) are deliberately NOT defaultable.
	Defaults *UploadDefaults `json:"defaults,omitempty"`
	// Devices are saved offline-share destinations, usable as `--dest <name>`.
	Devices []DeviceAlias `json:"devices,omitempty"`
	// TrustedPeers are alias names or IPs whose inbound offline transfers are
	// auto-accepted without a password (security trade-off; set with a warning).
	TrustedPeers []string `json:"trusted_peers,omitempty"`
}

func LoadConfig

func LoadConfig() (Config, error)

func LoadConfigAt

func LoadConfigAt(path string) (Config, error)

func (*Config) DeleteDeviceAlias

func (c *Config) DeleteDeviceAlias(name string) bool

DeleteDeviceAlias removes an alias, returning whether one was removed.

func (*Config) DeleteTrustedPeer

func (c *Config) DeleteTrustedPeer(ref string) bool

DeleteTrustedPeer removes a trusted ref, returning whether one was removed.

func (Config) ResolveDeviceAlias

func (c Config) ResolveDeviceAlias(name string) (string, bool)

ResolveDeviceAlias returns the saved address for an alias name.

func (Config) ResolvedReshareDefault

func (c Config) ResolvedReshareDefault() *bool

ResolvedReshareDefault returns the standing reshare default, preferring the new Defaults.Reshare and falling back to the legacy top-level Reshare (O-C1 migration).

func (*Config) SetDeviceAlias

func (c *Config) SetDeviceAlias(name, addr string)

SetDeviceAlias adds or updates an alias (case-insensitive name match).

func (*Config) SetTrustedPeer

func (c *Config) SetTrustedPeer(ref string)

SetTrustedPeer marks an alias name or IP as trusted (deduplicated).

func (Config) TrustedIPs

func (c Config) TrustedIPs() []string

TrustedIPs resolves every trusted ref to a bare IP: literal IPs pass through, alias names resolve to their saved address's host. Non-resolvable refs are skipped. These IPs auto-accept inbound offline transfers without a password.

type CreateAPITokenResponse

type CreateAPITokenResponse struct {
	Token    string       `json:"token"`
	APIToken APITokenInfo `json:"api_token"`
}

CreateAPITokenResponse carries the raw token (shown exactly once) plus metadata.

type Credential

type Credential struct {
	SchemaVersion    int    `json:"schema_version,omitempty"`
	APIBase          string `json:"api_base"`
	Token            string `json:"token"`
	Email            string `json:"email"`
	DeviceSessionID  string `json:"device_session_id,omitempty"`
	DevicePublicKey  string `json:"device_public_key,omitempty"`
	DevicePrivateKey string `json:"device_private_key,omitempty"`
}

func LoadCredential

func LoadCredential() (Credential, error)

func LoadCredentialAt

func LoadCredentialAt(path string) (Credential, error)

type DeviceAlias

type DeviceAlias struct {
	Name string `json:"name"`
	Addr string `json:"addr"`
}

DeviceAlias maps a friendly name to an offline-share address (ip[:port] or an s2u:// pairing string). Used by `s2u config set device alias` and `--dest`.

type DeviceCodeRequest

type DeviceCodeRequest struct {
	DeviceName    string `json:"device_name,omitempty"`
	MachineID     string `json:"machine_id,omitempty"`
	OS            string `json:"os,omitempty"`
	Arch          string `json:"arch,omitempty"`
	ClientVersion string `json:"client_version,omitempty"`
}

type DeviceCodeResponse

type DeviceCodeResponse struct {
	DeviceCode              string `json:"device_code"`
	UserCode                string `json:"user_code"`
	VerificationURI         string `json:"verification_uri"`
	VerificationURIComplete string `json:"verification_uri_complete"`
	Interval                int    `json:"interval"`
	ExpiresIn               int    `json:"expires_in"`
}

type DeviceKeyPair

type DeviceKeyPair struct {
	PublicKey  string
	PrivateKey string
}

func NewDeviceKeyPair

func NewDeviceKeyPair() (DeviceKeyPair, error)

type DeviceLimitDetails

type DeviceLimitDetails struct {
	Limit    int             `json:"limit"`
	Sessions []DeviceSession `json:"sessions"`
}

func DeviceLimitDetailsFromError

func DeviceLimitDetailsFromError(err error) (DeviceLimitDetails, bool)

type DeviceMetadata

type DeviceMetadata struct {
	DeviceName string
	MachineID  string
	OS         string
	Arch       string
	Hostname   string
}

func DetectDeviceMetadata

func DetectDeviceMetadata(deviceName string) (DeviceMetadata, error)

type DeviceSession

type DeviceSession struct {
	ID         string `json:"id"`
	DeviceName string `json:"device_name"`
	MachineID  string `json:"machine_id"`
	ClientType string `json:"client_type"`
	PublicKey  string `json:"public_key"`
	CreatedAt  string `json:"created_at"`
	LastUsedAt string `json:"last_used_at"`
	ExpiresAt  string `json:"expires_at"`
	Current    bool   `json:"current"`
}

type DeviceTokenResponse

type DeviceTokenResponse struct {
	Credential      string   `json:"credential"`
	DeviceSessionID string   `json:"device_session_id"`
	Scopes          []string `json:"scopes"`
	ExpiresAt       string   `json:"expires_at"`
}

type InboxResponse

type InboxResponse struct {
	Shares []InboxShare `json:"shares"`
}

type InboxShare

type InboxShare struct {
	PublicID       string `json:"public_id"`
	FileName       string `json:"file_name"`
	SizeBytes      uint64 `json:"size_bytes"`
	ContentType    string `json:"content_type"`
	ContentClass   string `json:"content_class"`
	SealedKey      string `json:"sealed_key"`
	CreatedAt      string `json:"created_at"`
	ExpiresAt      string `json:"expires_at"`
	FromDeviceName string `json:"from_device_name"`
}

type InstallEvent

type InstallEvent struct {
	InstallID string `json:"install_id"`
	EventType string `json:"event_type,omitempty"`
	Version   string `json:"version,omitempty"`
	OS        string `json:"os,omitempty"`
	Arch      string `json:"arch,omitempty"`
}

InstallEvent is an anonymous install/update telemetry ping (todo §J.4).

type ListDevicesResponse

type ListDevicesResponse struct {
	Sessions []DeviceSession `json:"sessions"`
}

type ListIndexEntry

type ListIndexEntry struct {
	Serial   int    `json:"serial"`
	PublicID string `json:"public_id"`
	FileName string `json:"file_name"`
}

func LoadListIndex

func LoadListIndex() ([]ListIndexEntry, error)

func LoadListIndexAt

func LoadListIndexAt(path string) ([]ListIndexEntry, error)

type ListSharesResponse

type ListSharesResponse struct {
	Shares []Share `json:"shares"`
}

type LiveFlushResponse

type LiveFlushResponse struct {
	PublicID string `json:"public_id"`
	Version  uint64 `json:"version"`
	SHA256   string `json:"sha256"`
	Size     uint64 `json:"size"`
}

type LivePutRequest

type LivePutRequest struct {
	Content     string `json:"content"`
	CRC32       string `json:"crc32"`
	ContentType string `json:"content_type,omitempty"`
}

type LivePutResponse

type LivePutResponse struct {
	Changed    bool   `json:"changed"`
	CRC32      string `json:"crc32"`
	Size       uint64 `json:"size"`
	TTLSeconds int    `json:"ttl_seconds"`
}

type MeResponse

type MeResponse struct {
	AccountID string   `json:"account_id"`
	UserID    string   `json:"user_id"`
	Email     string   `json:"email"`
	PlanID    string   `json:"plan_id"`
	PlanName  string   `json:"plan_name"`
	Source    string   `json:"source"`
	Scopes    []string `json:"scopes,omitempty"`
	// MCPEnabled is the hosted-MCP kill-switch (plan entitlement AND the global
	// flag). A pointer so an older API that omits the field is treated as enabled
	// (nil), leaving the per-scope checks to gate access.
	MCPEnabled *bool `json:"mcp_enabled,omitempty"`
}

type OnboardingStatus

type OnboardingStatus struct {
	Onboarded       bool   `json:"onboarded"`
	ConsentRequired bool   `json:"consent_required"`
	ConsentVersion  string `json:"consent_version"`
}

OnboardingStatus reports whether the account has completed onboarding and whether the current terms/data-share consent still needs accepting.

type P2PICEServer

type P2PICEServer struct {
	URLs       []string `json:"urls"`
	Username   string   `json:"username,omitempty"`
	Credential string   `json:"credential,omitempty"`
}

P2PICEServer is a STUN/TURN server with time-limited credentials, issued by the room-authorization endpoint.

type P2PRoomAuth

type P2PRoomAuth struct {
	Room       string         `json:"room"`
	Role       string         `json:"role"`
	Token      string         `json:"token"`
	ExpiresAt  string         `json:"expires_at"`
	RelayURL   string         `json:"relay_url"`
	ICEServers []P2PICEServer `json:"ice_servers"`
}

P2PRoomAuth is the API's authorization for one relay room. The API is where the p2p_streaming_enabled entitlement is actually enforced — the relay only verifies the signature on the token minted here (ADR-019).

type PendingInboxResponse

type PendingInboxResponse struct {
	Shares []PendingInboxShare `json:"shares"`
}

type PendingInboxShare

type PendingInboxShare struct {
	PublicID       string `json:"public_id"`
	FileName       string `json:"file_name"`
	SizeBytes      uint64 `json:"size_bytes"`
	ContentType    string `json:"content_type"`
	SenderEmail    string `json:"sender_email"`
	FromDeviceName string `json:"from_device_name"`
	CreatedAt      string `json:"created_at"`
	ExpiresAt      string `json:"expires_at"`
}

type PendingResealEntry

type PendingResealEntry struct {
	SharePublicID  string    `json:"share_public_id"`
	ContentKey     string    `json:"content_key"` // base64 of the 32-byte AES-256-GCM data key
	RecipientEmail string    `json:"recipient_email"`
	CreatedAt      time.Time `json:"created_at"`
}

type PendingResealStore

type PendingResealStore map[string]PendingResealEntry

PendingResealStore maps a share's public id to its retained content key.

func LoadPendingReseal

func LoadPendingReseal() (PendingResealStore, error)

LoadPendingReseal reads the retained-key store, returning an empty (non-nil) store when the file does not exist yet. TTL-expired entries are dropped on read.

type PresignedUpload

type PresignedUpload struct {
	URL     string            `json:"url"`
	Method  string            `json:"method"`
	Headers map[string]string `json:"headers"`
}

type ResealEntry

type ResealEntry struct {
	ShareID         string `json:"share_id"`
	RecipientEmail  string `json:"recipient_email"`
	TargetSessionID string `json:"target_session_id"`
	PublicKey       string `json:"public_key"`
}

ResealEntry is one item in the sender's re-seal queue: an in-flight share whose recipient re-keyed. The sender re-seals the retained content key to PublicKey and submits it against TargetSessionID (Option B, docs/design/teammate-phase-c.md §2).

type ResealQueueResponse

type ResealQueueResponse struct {
	Requests []ResealEntry `json:"requests"`
}

type RevokeAllResponse

type RevokeAllResponse struct {
	Revoked uint64 `json:"revoked"`
}

type SecretFinding

type SecretFinding struct {
	RuleID      string
	Description string
	Line        int
	Redacted    string
	// Entropy is the gitleaks Shannon entropy of the match (0 when the rule is
	// not entropy-based); exposed for future tuning.
	Entropy float32
	// HighConfidence is true for named, high-precision credential rules (private
	// keys, cloud/provider tokens) — the class that agent/MCP uploads HARD-block.
	HighConfidence bool
}

type SecretScanOptions

type SecretScanOptions struct {
	MaxBytes int64
}

type SecretScanResult

type SecretScanResult struct {
	Findings     []SecretFinding
	Skipped      bool
	SkipReason   string
	ScannedBytes int64
	Truncated    bool
}

func ScanBytesForSecrets

func ScanBytesForSecrets(content []byte, opts SecretScanOptions) (SecretScanResult, error)

ScanBytesForSecrets runs the same gitleaks scan over an in-memory buffer (e.g. the text of a `share_text` upload, which has no file on disk). Same skip rules (binary/non-UTF8) and byte cap as ScanFileForSecrets.

func ScanFileForSecrets

func ScanFileForSecrets(path string, opts SecretScanOptions) (SecretScanResult, error)

func (SecretScanResult) HasHighConfidenceSecret

func (r SecretScanResult) HasHighConfidenceSecret() bool

HasHighConfidenceSecret reports whether any finding is a high-confidence secret.

type Share

type Share struct {
	PublicID            string   `json:"public_id"`
	FileName            string   `json:"file_name"`
	CreatedAt           string   `json:"created_at"`
	SizeBytes           uint64   `json:"size_bytes"`
	SHA256              string   `json:"sha256"`
	Status              string   `json:"status"`
	ExpiresAt           string   `json:"expires_at"`
	DownloadCount       uint64   `json:"download_count"`
	MaxDownloads        uint64   `json:"max_downloads"`
	ViewCount           uint64   `json:"view_count"`
	MaxViews            uint64   `json:"max_views"`
	Disabled            bool     `json:"disabled"`
	DisabledAt          string   `json:"disabled_at"`
	ContentClass        string   `json:"content_class"`
	Encrypted           bool     `json:"encrypted"`
	EncryptionAlgo      string   `json:"encryption_algo"`
	RecipientRestricted bool     `json:"recipient_restricted"`
	Recipients          []string `json:"recipients,omitempty"`
	AllowedDomains      []string `json:"allowed_domains,omitempty"`
	DeniedDomains       []string `json:"denied_domains,omitempty"`
	DeviceSessionID     string   `json:"device_session_id"`
	DeviceName          string   `json:"device_name"`
	LiveUpdate          bool     `json:"live_update"`
	Version             uint64   `json:"version"`
}

type ShareAccessEvent

type ShareAccessEvent struct {
	OccurredAt string `json:"occurred_at"`
	IP         string `json:"ip"`
	Country    string `json:"country"`
	Client     string `json:"client"`
	EventType  string `json:"event_type"`
}

type ShareAnalyticsResponse

type ShareAnalyticsResponse struct {
	Views           uint64                   `json:"views"`
	Downloads       uint64                   `json:"downloads"`
	UniqueVisitors  uint64                   `json:"unique_visitors"`
	FirstAccessedAt string                   `json:"first_accessed_at"`
	LastAccessedAt  string                   `json:"last_accessed_at"`
	Timeline        []AnalyticsTimelinePoint `json:"timeline"`
	Recent          []ShareAccessEvent       `json:"recent"`
}

type ShareRef

type ShareRef struct {
	PublicID   string `json:"public_id"`
	Link       string `json:"link"`
	LiveUpdate bool   `json:"live_update"`
	Version    uint64 `json:"version"`
	Targeted   bool   `json:"targeted,omitempty"`
}

type SourceRegistry

type SourceRegistry map[string]SourceRegistryEntry

func AddSourceRegistryEntry

func AddSourceRegistryEntry(registry SourceRegistry, absPath string, entry SourceRegistryEntry) SourceRegistry

func LoadSourceRegistry

func LoadSourceRegistry() (SourceRegistry, error)

func LoadSourceRegistryAt

func LoadSourceRegistryAt(path string) (SourceRegistry, error)

type SourceRegistryEntry

type SourceRegistryEntry struct {
	PublicID string `json:"public_id"`
	Link     string `json:"link"`
}

type TeammateDevice

type TeammateDevice struct {
	DeviceID  string `json:"device_id"`
	PublicKey string `json:"public_key"`
}

type TeammateDeviceList

type TeammateDeviceList struct {
	Mode    string           `json:"mode"`
	Code    string           `json:"code"`
	Devices []TeammateDevice `json:"devices"`
}

type TeammatePolicy

type TeammatePolicy struct {
	Mode    string               `json:"mode"`
	Senders []TeammateSenderPref `json:"senders"`
}

type TeammateSenderPref

type TeammateSenderPref struct {
	Email string `json:"email"`
	Mode  string `json:"mode"`
}

type UpdateCheckCache

type UpdateCheckCache struct {
	LastCheckedAt time.Time `json:"last_checked_at"`
	LatestVersion string    `json:"latest_version,omitempty"`
}

func LoadUpdateCheckCache

func LoadUpdateCheckCache() (UpdateCheckCache, error)

func LoadUpdateCheckCacheAt

func LoadUpdateCheckCacheAt(path string) (UpdateCheckCache, error)

type UpdateCheckResponse

type UpdateCheckResponse struct {
	CurrentVersion  string          `json:"current_version"`
	LatestVersion   string          `json:"latest_version"`
	UpdateAvailable bool            `json:"update_available"`
	Platform        string          `json:"platform"`
	Downloads       UpdateDownloads `json:"downloads"`
}

type UpdateDownloads

type UpdateDownloads struct {
	ArchiveURL string `json:"archive_url"`
	CRC32URL   string `json:"crc32_url"`
	CRC32      string `json:"crc32"`
	SizeBytes  int64  `json:"size_bytes"`
	SHA256     string `json:"sha256,omitempty"`
}

type UploadCompleteResponse

type UploadCompleteResponse struct {
	PublicID  string `json:"public_id"`
	Status    string `json:"status"`
	ExpiresAt string `json:"expires_at"`
	Version   uint64 `json:"version"`
}

type UploadCreateRequest

type UploadCreateRequest struct {
	FileName     string `json:"file_name"`
	SizeBytes    uint64 `json:"size_bytes"`
	ContentClass string `json:"content_class,omitempty"`
	ContentType  string `json:"content_type,omitempty"`
	ExpiresIn    string `json:"expires_in,omitempty"`
	// NoExpiry keeps the share indefinitely (no expiry). When true, ExpiresIn is
	// ignored server-side. See --keep / --expires=none.
	NoExpiry       bool           `json:"no_expiry,omitempty"`
	SHA256         string         `json:"sha256,omitempty"`
	SourceRef      string         `json:"source_ref,omitempty"`
	New            bool           `json:"new"`
	Password       string         `json:"password,omitempty"`
	OneTime        bool           `json:"one_time,omitempty"`
	Encrypted      bool           `json:"encrypted,omitempty"`
	EncryptionAlgo string         `json:"encryption_algo,omitempty"`
	Recipients     []string       `json:"recipients,omitempty"`
	MaxViews       uint64         `json:"max_views,omitempty"`
	AllowedDomains []string       `json:"allowed_domains,omitempty"`
	DeniedDomains  []string       `json:"denied_domains,omitempty"`
	Live           bool           `json:"live,omitempty"`
	TargetDevice   string         `json:"target_device,omitempty"`
	SealedKey      string         `json:"sealed_key,omitempty"`
	RecipientEmail string         `json:"recipient_email,omitempty"`
	Targets        []UploadTarget `json:"targets,omitempty"`
	// Source declares the client origin for audit attribution; only "mcp" is
	// honored server-side (an AI-agent upload).
	Source string `json:"source,omitempty"`
	// AllowReshare opts a PRIVATE share into being resharable by recipients
	// (ADR-024, --unrestrict). Pointer so an unset value omits the field and the
	// server default (false) applies; ignored for public shares.
	AllowReshare *bool `json:"allow_reshare,omitempty"`
	// Note is a short message the sharer attaches, shown to viewers on the share
	// page.
	Note string `json:"note,omitempty"`
}

type UploadCreateResponse

type UploadCreateResponse struct {
	Upload               PresignedUpload `json:"upload"`
	Share                ShareRef        `json:"share"`
	UploadSessionID      string          `json:"upload_session_id"`
	ExpiresAt            string          `json:"expires_at"`
	Link                 string          `json:"link"`
	SkippedUpload        bool            `json:"skipped_upload"`
	EmailSharesRemaining *int            `json:"email_shares_remaining,omitempty"`
}

type UploadDefaults

type UploadDefaults struct {
	Expires        *string  `json:"expires,omitempty"`
	Reshare        *bool    `json:"reshare,omitempty"`
	Encrypt        *bool    `json:"encrypt,omitempty"`
	MaxViews       *uint64  `json:"max_views,omitempty"`
	NoScan         *bool    `json:"no_scan,omitempty"`
	AllowedDomains []string `json:"allowed_domains,omitempty"`
	DeniedDomains  []string `json:"denied_domains,omitempty"`
}

UploadDefaults holds tri-state standing defaults for upload options. A nil pointer / nil slice means "unset" (fall through to the compiled/server default).

func (*UploadDefaults) IsEmpty

func (d *UploadDefaults) IsEmpty() bool

IsEmpty reports whether every standing default is unset, so callers can drop the Defaults object entirely (keeping `"defaults": {}` out of config.json).

type UploadTarget

type UploadTarget struct {
	TargetDeviceSessionID string `json:"target_device_session_id"`
	SealedKey             string `json:"sealed_key"`
}

type UsageResponse

type UsageResponse struct {
	StorageUsedBytes        uint64   `json:"storage_used_bytes"`
	StorageQuotaBytes       uint64   `json:"storage_quota_bytes"`
	MonthlyUploadBytes      uint64   `json:"monthly_upload_bytes"`
	MonthlyUploadLimitBytes uint64   `json:"monthly_upload_limit_bytes"`
	ActiveShares            uint64   `json:"active_shares"`
	MaxActiveShares         uint64   `json:"max_active_shares"`
	MaxFileSizeBytes        uint64   `json:"max_file_size_bytes"`
	MaxDownloadsPerShare    uint64   `json:"max_downloads_per_share"`
	DefaultExpiryHours      uint64   `json:"default_expiry_hours"`
	MaximumExpiryHours      uint64   `json:"maximum_expiry_hours"`
	AllowedContentClasses   []string `json:"allowed_content_classes"`
	PasswordProtection      bool     `json:"password_protection_enabled"`
	OneTimeDownload         bool     `json:"one_time_download_enabled"`
	ClientSideEncryption    bool     `json:"client_side_encryption_enabled"`
}

Directories

Path Synopsis
Package lanshare implements Share2Us's offline, account-free, direct peer-to-peer file transfer over a LAN / Tailscale / WireGuard / any reachable IP.
Package lanshare implements Share2Us's offline, account-free, direct peer-to-peer file transfer over a LAN / Tailscale / WireGuard / any reachable IP.
Package p2p implements the Share2Us peer-to-peer streaming transport (Phase 3): a single ordered/reliable WebRTC data channel between two peers, with SDP/ICE signaling brokered by a lightweight relay WebSocket.
Package p2p implements the Share2Us peer-to-peer streaming transport (Phase 3): a single ordered/reliable WebRTC data channel between two peers, with SDP/ICE signaling brokered by a lightweight relay WebSocket.

Jump to

Keyboard shortcuts

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