appstore

package
v1.0.1-beta.1 Latest Latest
Warning

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

Go to latest
Published: May 29, 2026 License: AGPL-3.0 Imports: 20 Imported by: 0

Documentation

Overview

Package appstore is the coreapi.Service shim that hosts the app store inside the pilot daemon. It implements coreapi.Service (Name/Order/Start/ Stop) and wraps the supervisor that spawns + brokers every installed app.

The shim does not import the daemon's coreapi package directly, so the app-store module stays self-buildable. The Service type's method shapes are nominally identical to coreapi.Service; the daemon's main.go can register *Service against the interface without an explicit adapter as long as the type signatures stay in sync. (See INTEGRATION.md for the contract.)

Index

Constants

This section is empty.

Variables

View Source
var EmbeddedCatalogPubkey = make([]byte, 32)

EmbeddedCatalogPubkey is the production trust anchor for the catalog. REPLACE with the real key before release; the placeholder here is the all-zeros key so a misconfigured build refuses to verify anything (any real signature will fail against zero).

View Source
var ErrAppNotInstalled = errors.New("appstore: app not installed")

ErrAppNotInstalled is returned by Call/Apps lookups for unknown app IDs.

View Source
var ErrAppNotReady = errors.New("appstore: app not ready")

ErrAppNotReady is returned by Call when the app's socket hasn't appeared yet (still starting up, or it crashed and hasn't respawned).

Functions

This section is empty.

Types

type AppInfo

type AppInfo struct {
	ID              string   `json:"id"`
	AppVersion      string   `json:"app_version"`
	ManifestVersion int      `json:"manifest_version"`
	Methods         []string `json:"methods"`
	Protection      string   `json:"protection"`
	Ready           bool     `json:"ready"`
	Suspended       bool     `json:"suspended,omitempty"` // crash-loop budget spent
}

AppInfo is the public summary of one installed app, exposed via Service.Apps. Strips internal paths the daemon shouldn't expose.

type Config

type Config struct {
	// InstallRoot is where the app store keeps each installed app's
	// pinned manifest, binary, data, identity, and audit log.
	// Default: ~/.pilot/apps.
	InstallRoot string

	// CatalogPubkey is the ed25519 public key the app store uses to
	// verify the signed catalog Merkle root. In production this is
	// compile-time-embedded into the daemon binary (see
	// EmbeddedCatalogPubkey). For dev mode, leave zero and pass a
	// dev key via NewServiceWithKey.
	CatalogPubkey []byte

	// Logger optionally redirects internal messages. When nil the
	// service logs via the standard log package.
	Logger *log.Logger

	// RescanInterval controls how often the supervisor re-walks
	// InstallRoot looking for newly-landed apps (e.g. dropped by
	// `pilotctl appstore install` while the daemon is running).
	// Zero defaults to 30s. Set very short (e.g. 100ms) in tests.
	RescanInterval time.Duration

	// AuditLogMaxBytes is the per-app supervisor.log size threshold
	// at which a single-step rotation fires (active → .1). Zero
	// defaults to maxAuditLogSize (10MB). Tests set this low to
	// exercise the rotation path without writing megabytes.
	AuditLogMaxBytes int64
}

Config carries the integration-time settings. Passed by the daemon's main.go composition root; defaults are picked up when fields are zero.

type Deps

type Deps struct {
	Streams  any // coreapi.Streams — Dial, Listen, SendDatagram
	Identity any // coreapi.Identity — NodeID, Address, PublicKey, Sign
	Resolver any
	Events   any // coreapi.EventBus — Publish, Subscribe
	Logger   any
	Trust    any
}

Deps is the duck-typed shape of coreapi.Deps the daemon hands plugins. Kept independent of the real coreapi package so app-store stays self-buildable; the field names + signatures must match pkg/coreapi/lifecycle.go exactly.

When the daemon's main.go registers *Service it passes the real coreapi.Deps; Go's structural typing makes this work as long as the methods used here are present on the real types.

type Service

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

Service implements coreapi.Service for the app store.

func NewService

func NewService(cfg Config) *Service

NewService constructs a Service using cfg. Defaults are filled in.

func (*Service) Apps

func (s *Service) Apps() []AppInfo

Apps returns a summary of every installed app the service is currently supervising. Returns nil before Start has run.

func (*Service) Call

func (s *Service) Call(ctx context.Context, appID, method string, args, out any) error

Call dispatches method+args into the named installed app via its app.sock. This is the broker entry point that lets other plugins, the daemon, or pilotctl talk to any installed app's IPC surface without dialing the socket directly.

Returns ErrAppNotInstalled when the app id is unknown, ErrAppNotReady when the spawned process hasn't bound its socket yet, or whatever error the app's own IPC handler returned.

func (*Service) Name

func (s *Service) Name() string

Name returns the plugin identifier reported to the runtime registry.

func (*Service) Order

func (s *Service) Order() int

Order returns the lifecycle priority. 120 = application layer, started after foundation (10-49) and trust (50-79), before sidecars (200+). Stop runs in reverse, so by the time we stop, peer plugins still up.

func (*Service) Start

func (s *Service) Start(ctx context.Context, deps Deps) error

Start scans InstallRoot for installed apps, verifies each binary's pinned sha256, spawns the child processes, and parks an IPC connection per app for broker forwarding. Returns the first hard failure that would leave the daemon in an unhealthy state; per-app failures only log and continue (one bad app shouldn't sink the daemon).

In tick 5 this is a skeleton: directory walk + log lines, no actual spawn. The supervisor wire-up happens in tick 6 when we have a real integration test against the daemon's coreapi.

func (*Service) Stop

func (s *Service) Stop(ctx context.Context) error

Stop signals the supervisor to shut down and waits up to the ctx's deadline (or 5s if no deadline set) for all child processes to exit.

Jump to

Keyboard shortcuts

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