apps

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Aug 5, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package apps manages installed applications: web frontends built on top of the agent's public API (vision document, section 7.6). An application never receives the agent's full privileges — it declares the permissions it needs in a manifest, and receives a session limited to exactly those (vision document, section 15.4; internal/auth issues and checks such sessions).

This is the minimal first slice (ADR-0026): the manifest only covers workflows.run. connectors.use and capabilities from the vision document are deliberately not modeled yet — there is no enforcement point for them, the same situation plugin permissions are in today (internal/plugins.CatalogEntry.Permissions is recorded but unchecked).

Index

Constants

View Source
const ManifestFileName = "patchcord-app.yaml"

ManifestFileName is the file an application's source/static directory must contain at its root (vision document, section 10.3).

View Source
const PackageExtension = ".patchcord-app"

PackageExtension is the conventional file extension for an application package produced by Pack (vision document, section 9.3: ".patchcord-app"). Install only inspects whether the path is a file or a directory, not this extension — it is a naming convention, not part of the format.

Variables

View Source
var ErrAlreadyExists = errors.New("app already exists")

ErrAlreadyExists is returned by Install when an application with the manifest's id is already installed.

View Source
var ErrInvalidManifest = errors.New("invalid app manifest")

ErrInvalidManifest is returned by ParseManifest and LoadManifest when the manifest is malformed or missing a required field.

View Source
var ErrNotFound = errors.New("app not found")

ErrNotFound is returned by Get and Uninstall when no application with the given id has been recorded.

Functions

func Pack

func Pack(sourceDir string, key ed25519.PrivateKey, w io.Writer) error

Pack archives sourceDir (which must contain a valid patchcord-app.yaml, vision document section 9.3: "Interface web statique et manifeste de permissions") into w as a gzip-compressed tar stream, plus a checksums.json covering it (see internal/packaging.SignedArchive). If key is non-nil, the package is also signed — key == nil (no --sign-key) produces a package with integrity data but no provenance. The result is what InstallPackage (and therefore `patchcord app install`) expects.

Only regular files and directories are supported; sourceDir must not contain symlinks or other special entries.

func Scaffold

func Scaffold(dir, id, version string) error

Scaffold writes a minimal patchcord-app.yaml and index.html to dir, ready for `app pack`/`app install` as-is. It returns an error if dir already exists and is not empty — Scaffold never overwrites.

func ScaffoldVite

func ScaffoldVite(dir, id, version string) error

ScaffoldVite writes a minimal Vite + TypeScript project to dir — no UI framework opinion, just enough to run `npm install && npm run build` and get an installable app directory out of it. It returns an error if dir already exists and is not empty — ScaffoldVite never overwrites.

Unlike Scaffold, the result is not installable as-is: patchcord-app.yaml lives under public/ so Vite's build copies it into dist/ alongside the bundled JS, matching the reference dashboard example (apps/examples/dashboard). Build first, then point app/bundle commands at dir's dist subdirectory:

cd dir && npm install && npm run build
patchcord app install dir/dist

func Uninstall

func Uninstall(ctx context.Context, db *sql.DB, id string) error

Uninstall removes an application. It returns ErrNotFound if no application with that id has been recorded.

Types

type App

type App struct {
	ID          string
	Version     string
	StaticDir   string
	Permissions AppPermissions
	CreatedAt   time.Time
}

App is one installed application, as recorded in the database.

func Get

func Get(ctx context.Context, db *sql.DB, id string) (*App, error)

Get returns one installed application by id. It returns ErrNotFound if no application with that id has been recorded.

func Install

func Install(ctx context.Context, db *sql.DB, sourceDir string) (*App, error)

Install reads sourceDir's manifest (patchcord-app.yaml) and records the application, serving its static files straight from sourceDir. There is no packaging or copy step yet — the real .patchcord-app bundle format (vision document, section 9.3) is deferred, see ADR-0026.

It returns ErrAlreadyExists if an application with the manifest's id is already installed, or an error wrapping ErrInvalidManifest if the manifest is malformed.

func InstallOrUpdate

func InstallOrUpdate(ctx context.Context, db *sql.DB, sourceDir string) (*App, error)

InstallOrUpdate is Install, except that installing over an application whose id is already recorded updates it in place (new version, static_dir, permissions) instead of returning ErrAlreadyExists. It backs `patchcord app dev`: since handleServeApp reads static_dir straight off disk on every request (no copy, no cache), an application registered this way is already "hot reloaded" for free — rebuilding it in place (e.g. `vite build --watch`) is visible on the next browser refresh with no further agent involvement. What InstallOrUpdate removes is the friction Install has for this loop: without it, iterating would require `app remove` before every `app install`.

func InstallPackage

func InstallPackage(ctx context.Context, db *sql.DB, dataDir, packagePath string, requireSignature bool) (*App, trust.PolicyResult, error)

InstallPackage installs an application from a .patchcord-app archive (Pack's output). Unlike Install, which serves an application straight from wherever its source directory happens to live, a package's contents are extracted under dataDir/apps/<id>/<version> — a location the agent owns for as long as the application stays installed, so the archive itself is free to move or disappear afterwards.

The package is verified (internal/packaging.Verify) before anything is installed: a checksum mismatch or an invalid signature aborts unconditionally. requireSignature additionally rejects a package that is unsigned, or signed by a key not trusted for its id (internal/trust) — when false, InstallPackage still returns the verification outcome so the caller can warn about either case instead of failing outright.

It returns ErrAlreadyExists if an application with the manifest's id is already installed, or an error wrapping ErrInvalidManifest if the packaged manifest is malformed.

func List

func List(ctx context.Context, db *sql.DB) ([]App, error)

List returns every installed application, ordered by id.

type AppPermissions

type AppPermissions struct {
	WorkflowsRun []string `json:"workflows_run"`
}

AppPermissions is the permission set an application's sessions are limited to (api/app/v1/manifest.schema.json). WorkflowsRun is the only kind enforced today — see the package doc comment.

type Manifest

type Manifest struct {
	ID          string
	Version     string
	Permissions AppPermissions
}

Manifest is the parsed content of an application's patchcord-app.yaml.

func LoadManifest

func LoadManifest(dir string) (*Manifest, error)

LoadManifest reads and parses dir's patchcord-app.yaml.

func ParseManifest

func ParseManifest(source []byte) (*Manifest, error)

ParseManifest parses and validates an application manifest from its YAML source, returning ErrInvalidManifest if a required field is missing or empty.

Jump to

Keyboard shortcuts

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