Documentation
¶
Overview ¶
Package wasmplugin runs filex "app plugins": WebAssembly modules executed inside the filex process by wazero (through the Extism host SDK), with no access to the host's filesystem, network, environment or database — only to the host functions filex exposes, each gated by a permission the administrator granted at install.
Why in-process wasm and not a subprocess or a sidecar ¶
The storage-plugin subsystem (internal/plugin) starts a plugin BINARY in filex's own container: same filesystem, same environment, FILEX_SECRET_KEY in reach. That is fine for a driver the operator built, and unacceptable for third-party code a user installs from a URL. A container per plugin needs a Docker socket somewhere; an OS sandbox is strong on Linux and absent on the other two platforms filex ships for. A wasm sandbox is the same on all three, costs no extra process, and cannot reach anything it is not handed.
What the runtime guarantees ¶
- wazero's compiler backend only (amd64/arm64). The interpreter is refused, not tolerated: measured elsewhere, it takes every core for minutes.
- A fresh instance per call: no state survives between users or jobs, memory is returned when the call ends.
- A memory ceiling (Manifest.MemoryPages) and a wall-clock budget per call; the instance is torn down when either is hit.
- No WASI filesystem preopens, no environment, no arguments.
- Compiled modules are cached on disk (WithCompilationCache), so a 20–50 MB Go module is compiled once per host, not once per boot.
Index ¶
- Constants
- Variables
- func Answered(v any) bool
- func AppPermKey(app, id string) string
- func ArchSupported() bool
- func CheckOpen(p *Installed, s *wire.Surface) error
- func CompatEnforced() bool
- func DecodeInstallBody(b []byte) (map[string]json.RawMessage, error)
- func EncodeJobText(t wire.Text) string
- func ExposedFiles(sh *model.Share) []wire.FileRef
- func FilexVersion() string
- func IsCode(err error, code string) bool
- func IsNewDocumentKey(key string) bool
- func JobRoot(params map[string]any) (confine.Root, bool)
- func JobText(stored, lang string) string
- func JobTimeout(l wire.Limits) int
- func JudgeFilexRange(rng string) (ok bool, requires, filex string, err error)
- func LocalizeNote(note, lang string) string
- func ManifestHandlers(m *Manifest) (open, thumb []assoc.AppHandler)
- func Matches(a wire.Applies, items []Item) bool
- func NewDocumentKey(plugin, ext string) string
- func NewJobID() string
- func NextTickBoundary(now time.Time) time.Time
- func OffersOnReadOnly(a *wire.Action, applies wire.Applies) bool
- func OutputOverride(params map[string]any) *wire.Output
- func ParseCatalogue(b []byte) ([]string, error)
- func PersonalStateKeys(keys []string, userID int64) []string
- func PinLength(raw any) int
- func PublicURL(base, token string) string
- func SanitizeSurface(s *wire.Surface)
- func SetJobRoot(params map[string]any, root confine.Root)
- func SetOutputOverride(params map[string]any, o *wire.Output)
- func StampJobRoot(params map[string]any, spec string)
- func StripHostParams(params map[string]any) map[string]any
- func TickTimeout(m *Manifest) int
- func UIPolicy(grants Grants, pkg string) (csp, allowlist string)
- func ValidOutputMode(m string) bool
- func ValidScheduleKey(key string) bool
- func ValueString(v any) string
- func WithActorIP(ctx context.Context, ip string) context.Context
- func WithScope(ctx context.Context, s *Scope) context.Context
- type ActionRow
- type ActionsAnswer
- type AppClock
- type AppNewDocument
- type AutoUpdated
- type CAList
- type CANote
- type CallError
- type Cataloguer
- type Compat
- type Compiled
- func (c *Compiled) Call(ctx context.Context, export string, input []byte, budget time.Duration) ([]byte, error)
- func (c *Compiled) Close(ctx context.Context) error
- func (c *Compiled) Describe(ctx context.Context, locale string) (*wire.Manifest, error)
- func (c *Compiled) HasExport(ctx context.Context, export string) (bool, error)
- type DryRunAnswer
- type DryRunEngine
- type DryRunInstalled
- type DryRunUpgrade
- type FieldProblem
- type GatedRule
- type GitHubInput
- type Grants
- type HostFunc
- type InstallError
- type InstallInput
- type InstallRefusal
- type Installed
- type Item
- type JobOpen
- type JobOutput
- type JobQueue
- type LanguageRow
- type LogLine
- type Manifest
- func (m *Manifest) Action(id string) (*wire.Action, bool)
- func (m *Manifest) CallTimeout() int
- func (m *Manifest) Grants() Grants
- func (m *Manifest) MemoryPages() int
- func (m *Manifest) NeedsModule() bool
- func (m *Manifest) UIViews() map[string]*wire.View
- func (m *Manifest) UserPermission(id string) (wire.UserPermission, bool)
- func (m *Manifest) Validate() error
- func (m *Manifest) View(id string) (*wire.View, bool)
- func (m *Manifest) WritesElsewhere() bool
- type Need
- type OfficeConverter
- type OfficeError
- type OfficeRequest
- type Options
- type OutputSink
- type OverrideRow
- type PageFile
- type PageInfo
- type PdfRule
- type Permission
- type PermissionRow
- type PreviousVersion
- type Registry
- func (r *Registry) ActionsFor(ctx context.Context, isAdmin bool) (*ActionsAnswer, error)
- func (r *Registry) All() []*Installed
- func (r *Registry) AppLabel(name string) wire.Text
- func (r *Registry) AppLimits(app string) (int64, time.Duration, bool)
- func (r *Registry) BackgroundUpdates() bool
- func (r *Registry) ByID(id int64) (*Installed, bool)
- func (r *Registry) ByName(name string) (*Installed, bool)
- func (r *Registry) CACertPEM(ctx context.Context, tenantID int64) (string, error)
- func (r *Registry) CACertsPEM(ctx context.Context, tenantID int64) (string, error)
- func (r *Registry) CAs(ctx context.Context, tenantID int64) ([]CAList, error)
- func (r *Registry) CheckPIN(ctx context.Context, sh *model.Share, pin string) error
- func (r *Registry) CheckUpdates(ctx context.Context) (*UpdateReport, error)
- func (r *Registry) Close(ctx context.Context)
- func (r *Registry) DecorateOps(ctx context.Context, rows []*ops.Op)
- func (r *Registry) Dir() string
- func (r *Registry) DrawThumbnail(ctx context.Context, app string, req assoc.DrawRequest) ([]byte, error)
- func (r *Registry) Engines(ctx context.Context) map[string]bool
- func (r *Registry) FetchGitHub(ctx context.Context, in GitHubInput) (*InstallInput, error)
- func (r *Registry) FetchURL(ctx context.Context, in URLInput) (*InstallInput, error)
- func (r *Registry) FetchUpdate(ctx context.Context, id int64) (*InstallInput, error)
- func (r *Registry) GitHubManifest(ctx context.Context, repo, ref string) ([]byte, error)
- func (r *Registry) ImportCA(ctx context.Context, tenantID int64, certPEM, keyPEM []byte) (*signingKey, error)
- func (r *Registry) Install(ctx context.Context, in *InstallInput) (*Status, *DryRunAnswer, error)
- func (r *Registry) InstanceID() string
- func (r *Registry) LanguageRows(m *Manifest) []LanguageRow
- func (r *Registry) LastUpdateCheck(ctx context.Context) time.Time
- func (r *Registry) LicenseHold(app string) string
- func (r *Registry) LinkHolds(ctx context.Context, sh *model.Share, storageID int64, rel string) bool
- func (r *Registry) LinkOf(sh *model.Share) *db.AppLink
- func (r *Registry) Load(ctx context.Context) error
- func (r *Registry) LoadPage(ctx context.Context, token string) (*model.Share, *Installed, error)
- func (r *Registry) LockReason(l *model.AppPluginLock) (string, wire.Text)
- func (r *Registry) Locks(ctx context.Context, storageID int64) ([]*model.AppPluginLock, error)
- func (r *Registry) Logs(id int64, after int64) ([]LogLine, int64, error)
- func (r *Registry) LookupUsers(ctx context.Context, q string) ([]UserRow, error)
- func (r *Registry) MaxOutputBytes() int64
- func (r *Registry) MaxUIBytes() int64
- func (r *Registry) MintUnlock(token string) string
- func (r *Registry) NewDocument(key string) (AppNewDocument, bool)
- func (r *Registry) NewDocumentBytes(ctx context.Context, key string) ([]byte, error)
- func (r *Registry) NewDocuments() []AppNewDocument
- func (r *Registry) OpenHandlers() []assoc.AppHandler
- func (r *Registry) Overrides(ctx context.Context, id int64) ([]OverrideRow, error)
- func (r *Registry) PageAnchor(ctx context.Context, sh *model.Share) (int64, string)
- func (r *Registry) PageEvent(ctx context.Context, sh *model.Share, p *Installed, in wire.ViewEventInput, ...) (*wire.Surface, error)
- func (r *Registry) PageFile(sh *model.Share, ref string) (*PageFile, *os.File, error)
- func (r *Registry) PageInfo(sh *model.Share, p *Installed, unlocked bool) *PageInfo
- func (r *Registry) PutOverrides(ctx context.Context, id int64, rows []OverrideRow) error
- func (r *Registry) PutSettings(ctx context.Context, id int64, values map[string]string) error
- func (r *Registry) PutThumbLimits(ctx context.Context, id int64, l ThumbLimits) (*ThumbLimitsAnswer, error)
- func (r *Registry) Remove(ctx context.Context, id int64) error
- func (r *Registry) RequiresSignature() bool
- func (r *Registry) ResolveAction(ctx context.Context, plugin, action string, isAdmin bool) (*Installed, *wire.Action, wire.Applies, error)
- func (r *Registry) Rollback(ctx context.Context, id int64, by *int64, lang string) (*Status, error)
- func (r *Registry) RotateCA(ctx context.Context, tenantID int64) error
- func (r *Registry) RunDueSchedule(ctx context.Context, now time.Time) (int, error)
- func (r *Registry) RunPluginAction(ctx context.Context, op *ops.Op, live func(done, total int64)) error
- func (r *Registry) ScheduleOf(ctx context.Context, id int64) ([]*model.AppPluginScheduleItem, error)
- func (r *Registry) SetCatalogue(keys []string)
- func (r *Registry) SetEnabled(ctx context.Context, id int64, on bool) (*Status, error)
- func (r *Registry) SetHTTPTransport(t http.RoundTripper)
- func (r *Registry) SetHeldPermissions(f func(ctx context.Context, u *model.User, p *Installed) []string)
- func (r *Registry) SetHomeResolver(f func(ctx context.Context, u *model.User) string)
- func (r *Registry) SetJobQueue(q JobQueue)
- func (r *Registry) SetLicenseHold(app, reason string)
- func (r *Registry) SetMailer(m mailSink)
- func (r *Registry) SetNotify(n notifySink)
- func (r *Registry) SetOffice(o OfficeConverter)
- func (r *Registry) SetOrigins(fn func(ctx context.Context, storageID int64) string)
- func (r *Registry) SetOutputSink(s OutputSink)
- func (r *Registry) SetPublicURL(base string)
- func (r *Registry) SetStorageResolver(fn func(int64) (storage.Driver, error))
- func (r *Registry) SetUIOrigin(origin string)
- func (r *Registry) SetUpgradeListener(f UpgradeListener)
- func (r *Registry) SetUserScope(fn func(ctx context.Context, u *model.User) context.Context)
- func (r *Registry) SetVisibility(fn func(ctx context.Context, u *model.User, storageID int64, rel string) bool)
- func (r *Registry) Settings(ctx context.Context, id int64) (map[string]string, []wire.Field, error)
- func (r *Registry) StartScheduler(ctx context.Context)
- func (r *Registry) StartSweeper(ctx context.Context)
- func (r *Registry) StartUpdater(ctx context.Context, enabled bool)
- func (r *Registry) StatusOf(p *Installed) *Status
- func (r *Registry) StorageName(ctx context.Context, id int64) string
- func (r *Registry) SweepPages(ctx context.Context) int
- func (r *Registry) SweepSchedule(ctx context.Context) int64
- func (r *Registry) ThumbLimits(ctx context.Context, id int64) (*ThumbLimitsAnswer, error)
- func (r *Registry) ThumbnailHandlers() []assoc.AppHandler
- func (r *Registry) Tick(ctx context.Context, p *Installed, now, windowEnd time.Time) (*wire.TickOutput, error)
- func (r *Registry) UICall(ctx context.Context, plugin, view string, storageID int64, rels []string, ...) (json.RawMessage, error)
- func (r *Registry) UIHandler(origin func(*http.Request) (string, bool)) http.Handler
- func (r *Registry) UILocale(code string) map[string]string
- func (r *Registry) UILocaleCodes() []string
- func (r *Registry) UILocaleList() []UILocaleInfo
- func (r *Registry) UIString(code, key string) (string, bool)
- func (r *Registry) Unlock(ctx context.Context, storageID int64, rel string) (bool, error)
- func (r *Registry) Upgrade(ctx context.Context, id int64, in *InstallInput) (*Status, *DryRunAnswer, error)
- func (r *Registry) UserPermissions() []UserPermRow
- func (r *Registry) VerifyUnlock(token, value string) bool
- func (r *Registry) ViewEvent(ctx context.Context, plugin, view string, storageID int64, rels []string, ...) (*wire.Surface, error)
- func (r *Registry) WakeSoon(ctx context.Context, pluginID int64, why string)
- type Runtime
- type Scope
- type SettingError
- type Status
- type ThumbLimits
- type ThumbLimitsAnswer
- type UIExternalRow
- type UIFileDiff
- type UIInfo
- type UILocaleInfo
- type UIRef
- type URLInput
- type UpdateInfo
- type UpdateReport
- type UpgradeListener
- type UserPermRow
- type UserRow
- type ViewRow
Constants ¶
const ( CodePluginError = "plugin_error" // the guest set an error message CodePluginTrap = "plugin_trap" // the guest crashed (unreachable, OOB…) CodePluginOOM = "plugin_oom" // the guest hit its memory ceiling CodeTimeout = "timeout" // the call outlived its budget CodeRefused = "refused" // describe disagrees with the manifest CodeUnsupported = "unsupported" // this host cannot run plugins (arch) CodeBusy = "busy" // every screen-call slot of the plugin is taken )
Outcome codes a guest call can end with. They are what the job row, the admin log and the user-facing message key on — never a wazero stack.
const ( ParamPageTokenHash = "page_token_hash" )
Parameter names only the HOST writes into a job row: the per-job output a person chose on a screen (outputOverrideKey, which runJob obeys without asking again), the root of the token that queued it (rootParamKey), and the stamps the public page door adds (which visitor's link acted — an app binds a signature to a signer by it).
const ( KindApp = "app" KindLanguagePack = "language_pack" )
The two kinds of app, as Status.Kind and DryRunAnswer.Kind say them.
const ( DefaultMemoryPages = 1024 // 64 MiB MaxMemoryPages = 4096 // 256 MiB DefaultCallTimeout = 15 // seconds, views/pages/describe MaxCallTimeout = 60 DefaultJobTimeout = 300 // seconds, action_run MaxJobTimeout = 900 // MaxTickTimeout caps the hourly wake-up. It is deliberately tighter // than a screen's ceiling: a screen has a person waiting and 60 s is // defensible, while a wake-up runs unattended and one that hangs holds // up every other app's schedule behind it. MaxTickTimeout = 30 )
Limits the host imposes on what a manifest may ask for.
const ( StateRunning = "running" StateDisabled = "disabled" StateRefused = "refused" StateFailed = "failed" // StateUnlicensed is a paid app whose license does not hold (revoked, // expired, never confirmed, its grace ended): loaded, not removed, and // running nothing until the license holds again (license_hold.go, // internal/appstore). It overlays "running" only. StateUnlicensed = "unlicensed" )
Plugin states.
const ( ErrCodeManifestInvalid = "manifest_invalid" ErrCodeSHA256Mismatch = "sha256_mismatch" ErrCodeSHA256Required = "sha256_required" ErrCodeSignatureRequired = "signature_required" ErrCodeSignatureInvalid = "signature_invalid" ErrCodePermissionsIncomplete = "permissions_incomplete" ErrCodePermissionsChanged = "permissions_changed" ErrCodeNameTaken = "name_taken" ErrCodeDescribeMismatch = "describe_mismatch" ErrCodeTooLarge = "too_large" ErrCodeDemo = "demo_refused" ErrCodeFetch = "fetch_failed" ErrCodeNotFound = "not_found" // ErrCodeIncompatible: the manifest's `filex` range leaves the running // filex out (compat.go). ErrCodeIncompatible = "incompatible" // ErrCodeUpToDate: "upgrade from its source" found nothing newer there // (updates.go FetchUpdate). ErrCodeUpToDate = "up_to_date" )
Install error codes.
const ( // FetchReasonBadRepo: the repository is not written as owner/name. FetchReasonBadRepo = "bad_repo" // FetchReasonManifestNotFound: no filex-app.json at any ref tried — a // repository that does not exist, is private, has no manifest at its // root, or a ref that does not exist. FetchReasonManifestNotFound = "manifest_not_found" // FetchReasonModuleNotFound: the manifest names a module address that // answers 404 — usually a release whose asset was never uploaded. FetchReasonModuleNotFound = "module_not_found" // FetchReasonUnreachable: no answer at all (DNS, network, TLS). FetchReasonUnreachable = "unreachable" // FetchReasonHTTPStatus: an answer, but not a success or a 404. FetchReasonHTTPStatus = "http_status" // FetchReasonBadURL: not an address filex downloads from - not https // (plain http only for loopback, with FILEX_PLUGIN_LOOPBACK_SOURCES), or a // private or local one (this machine, the private network, the cloud // metadata service), by its literal or by what its name resolves to, on // any redirect hop. FetchReasonBadURL = "bad_url" // FetchReasonMissingURL: a URL install without its addresses — the // manifest always, the module unless the manifest is a language pack. FetchReasonMissingURL = "missing_url" // FetchReasonTooLarge: the answer was larger than the cap. FetchReasonTooLarge = "too_large" // FetchReasonChanged: the source answered a different version between // the update check's read and the install's (updates.go). FetchReasonChanged = "changed" )
Why a fetch failed (InstallError.Reason on fetch_failed).
const ( // TickInterval is how often a scheduled app is woken. The wake-up is // re-armed to the next boundary of this interval, so an instance that // has been up for a week still wakes on the hour. TickInterval = time.Hour // MaxScheduleItems / MaxSchedulePaths are the wire contract's numbers, // not a second copy: the guest is told them in every TickInput and the // test kit checks an answer against them, so they are named once in // pkg/pluginkit/wire and enforced here. MaxScheduleItems = wire.ScheduleMaxItems MaxSchedulePaths = wire.ScheduleMaxPaths )
Bounds. Everything a wake-up can ask for is capped here; a plugin is told the two it has to plan around (MaxScheduleItems, MaxSchedulePaths) in its TickInput, so it can choose what to drop rather than having it chosen.
const ( FieldBadInt = "int" // not a whole number FieldBadBool = "bool" // not yes or no FieldBadText = "text" // not text (a list or an object where text was asked) FieldBadOption = "option" // not one of the offered options FieldBelowMin = "min" // a number below the field's min FieldAboveMax = "max" // a number above the field's max FieldRequired = "required" // a required field left empty FieldBadPin = "pin" // a code that is not the declared length (Limit) FieldBadDate = "date" // a date box that does not hold YYYY-MM-DD FieldBadNumber = "number" // a text box whose rule asks for a number FieldBadEmail = "email" // a text box whose rule asks for an address FieldTooShort = "too_short" // a text box under its rule's min length (Limit) FieldTooLong = "too_long" // a text box over its rule's max length (Limit) FieldBadShape = "shape" // a node's answer is not the shape it sends )
The reasons an answer does not fit the field that asked for it. They are the API's codes (`reason` on a refused setting) and the last part of the srvtext key that says them (`server.field.<code>`).
const ( // UpdateCurrent: nothing newer that this filex can run. UpdateCurrent = "current" // UpdateAvailable: a newer version waits for the administrator. UpdateAvailable = "available" // UpdateNeedsApproval: a newer version asks for more than was granted. UpdateNeedsApproval = "needs_approval" // UpdateIncompatible: newer versions exist, but none this filex can run. UpdateIncompatible = "incompatible" // UpdateFailed: an automatic update was tried and undone (filex 0.47, // which applied updates by itself; a row may still carry it). UpdateFailed = "failed" // UpdateCheckFailed: the source could not be read (nothing was tried). UpdateCheckFailed = "check_failed" )
What the last check found (UpdateInfo.Status).
const AuditActionThumbnailSent = "app_plugin.thumbnail_sent"
AuditActionThumbnailSent is the audit action of a thumbnail call that reached the network.
const ( // DefaultMaxUIBytes is the zipped bundle's ceiling unless // FILEX_APP_PLUGIN_MAX_UI_MB says otherwise. draw.io's whole editor is about // 60 MB zipped; 128 MiB leaves room without letting an app park arbitrary // data on the server. DefaultMaxUIBytes = 128 << 20 )
const DryRunEngineOffice = "office"
DryRunEngineOffice is DryRunEngine.Kind for the office engine.
const EnvAppClock = "FILEX_APP_CLOCK"
EnvAppClock names the variable: an RFC 3339 instant the apps' clock reads when the process starts, running at real speed from there. Empty or unset is the real clock.
const ErrCodeOutOfRange = "out_of_range"
ErrCodeOutOfRange: a limit outside its range (InstallError.Where names it).
const NoteCANotForDocumentsOnly = "ca_not_limited_to_document_signing"
NoteCANotForDocumentsOnly: the imported authority may sign more than documents (no extendedKeyUsage, or other purposes beside document signing).
const UIPrefix = "/_appui/"
UIPrefix is the route's first segment.
Variables ¶
var ( ErrPageNotFound = errors.New("page not found") ErrPageGone = errors.New("page is no longer available") )
Page errors the HTTP layer maps to status codes. The PIN-gate errors are internal/share's (ErrBadPIN / ErrLocked): there is one gate now.
var E2EPlaintextSetting = dbsetting.BoolSpec{ Key: "apps.e2e_plaintext", EnvVar: "FILEX_APPS_E2E_PLAINTEXT", Default: true, }
E2EPlaintextSetting is the administrator's switch for every app at once: off, no app is handed an encrypted file whatever it was granted. On by default - the grant itself is the administrator's yes, app by app, at install - and seeded once from FILEX_APPS_E2E_PLAINTEXT, then changed in the settings (`apps.e2e_plaintext`). Read at the point of use (both app doors, the capabilities answer), so a change applies at once.
var ErrOfficeTooLarge = errors.New("office engine: the result exceeds the per-file limit")
ErrOfficeTooLarge: the result is over the per-file limit.
var ErrOfficeUnconfigured = errors.New("office engine: no document server is configured")
ErrOfficeUnconfigured: no document server is configured.
var ErrUnsupportedArch = errors.New("wasmplugin: app plugins need an amd64 or arm64 host (wazero's interpreter is refused - it would take every core)")
ErrUnsupportedArch is returned by New on a CPU wazero has no compiler for.
var HostVersion = "dev"
HostVersion is what `describe` is told; filled by the server from its build.
var SurfaceNodeTypes = map[string]bool{ "text": true, "form": true, "steps": true, "list": true, "progress": true, "people-picker": true, "pin-input": true, "file-chooser": true, "pdf-fields": true, "signature-pad": true, "preview": true, "divider": true, "row": true, }
SurfaceNodeTypes is the v1 catalogue.
Functions ¶
func Answered ¶ added in v0.54.0
Answered says whether a value holds an answer at all: `false` and `0` do (an unticked box IS an answer), an empty or blank string and an empty list do not. Whether an answer is REQUIRED is a separate question.
func AppPermKey ¶ added in v0.49.0
AppPermKey is an app's user permission key, app.<app>.<id> — the same spelling as perm.AppKey (kept here so this package needs no perm import).
func ArchSupported ¶
func ArchSupported() bool
ArchSupported reports whether wazero has a compiler for this CPU.
func CheckOpen ¶
CheckOpen validates a surface's `open` against the plugin that answered: the screen it names must be that plugin's own, and it may not name both. The PATH is checked by the handler, which is where a caller's permissions are known — a screen must not become a way to look at a file the person asking could not open themselves.
func CompatEnforced ¶ added in v0.47.0
func CompatEnforced() bool
CompatEnforced reports whether this filex checks app ranges at all (false on a development build).
func DecodeInstallBody ¶
func DecodeInstallBody(b []byte) (map[string]json.RawMessage, error)
decodeJSONBody is a small helper for the handlers' JSON install bodies.
func EncodeJobText ¶ added in v0.46.0
EncodeJobText is t as a job column: one plain string when every language says the same (or only one was written), else every language, marked.
func ExposedFiles ¶
ExposedFiles lists the copies an app link exposed, straight off the row.
⚠ Deliberately a free function and not a Registry method: the no-JS page must be able to hand a visitor the document they were sent even on an instance where the plugin runtime is unavailable (an architecture without wasm, a plugin that failed to load). The copies are already on disk and belong to the share, not to the running app.
func FilexVersion ¶ added in v0.47.0
func FilexVersion() string
FilexVersion is the running filex as the Apps screen names it: x.y.z of a release, or the build's own version string on a development build.
func IsNewDocumentKey ¶ added in v0.48.0
IsNewDocumentKey reports whether a create request names an app's row.
func JobRoot ¶ added in v0.52.0
JobRoot reads the root a job's door stamped, ok=false when there is none.
⚠ Fails CLOSED: a stamp that is there but does not read as a root (not a string, no storage named) confines the job to no folder at all rather than to none - the host wrote it, so a stamp that will not parse is a broken row, never an unconfined one.
func JobText ¶ added in v0.46.0
JobText reads a job column in lang (wire.Text.Get: the language, its base language, English, any). A plain column — every row written before EncodeJobText, a progress line, the host's own words — comes back as it is.
func JobTimeout ¶
JobTimeout is the clamped budget for one action_run of an action.
func JudgeFilexRange ¶ added in v0.48.0
JudgeFilexRange reads a bare `filex` range the way an app's is read and judges it against the running filex — for a storage plugin's feed (plugin/updates.go), so there is one range grammar in filex, not two. ok is true on a development build (ranges are not enforced there) and for an empty range; err when the range does not parse.
func LocalizeNote ¶
LocalizeNote reads a schedule row's note in `lang`: a note written by wakeNote is composed in that language; a {lang: …} object (a row written before the record existed) is read the same way; anything else (an error) is returned as it is.
func ManifestHandlers ¶ added in v0.50.0
func ManifestHandlers(m *Manifest) (open, thumb []assoc.AppHandler)
ManifestHandlers are the handlers an app with this manifest would add: one per `viewer` view of its interface (open) and its `thumbnails` block (thumbnail) - what the install review's File types group lists before the app exists.
func Matches ¶
Matches reports whether an Applies rule accepts a selection described by (kind, ext, mime) per item. It is the one implementation the server uses for every check; the explorer mirrors it client-side for the menu.
func NewDocumentKey ¶ added in v0.48.0
NewDocumentKey is the key a row is asked for by.
func NextTickBoundary ¶
NextTickBoundary is when the wake-up after now falls: the next boundary of TickInterval, in UTC. Boundaries rather than "an hour from whenever it last ran" so a restart at 03:37 does not move every later wake-up to :37.
func OffersOnReadOnly ¶ added in v0.54.0
OffersOnReadOnly reports whether an action may be STARTED from the menu on a file of a read-only storage: it writes nothing there (its manifest output is neither `sibling` nor `version`, and its rule is not `writable`), or it opens a screen whose result may go into a folder the person chooses (`view` + `output.elsewhere`), which then asks where.
⚠⚠ ONE rule for the menu and the run. The run (handlers authorise, a menu click with no params) refuses exactly what this answers false for, and the action list carries the answer (ActionRow.ReadOnlyOK) — the explorer used to rebuild it from `output_mode` and `output_elsewhere` and offered every "elsewhere" action, including one with no screen, which the run then refused with 409 read_only.
func OutputOverride ¶
OutputOverride reads the per-job output stored in params, or nil.
func ParseCatalogue ¶
ParseCatalogue reads the embedded catalogue file (a flat key → English object — the exact shape of one `ui_locales` language) into its keys.
func PersonalStateKeys ¶
PersonalStateKeys is the view of a file's state keys (`<plugin>:<key>`) that ONE person gets: a personal key `<key>@<id>` (wire.PersonalState) is that person's own and reads `<key>@me`; anybody else's is left out, so a listing never says who else has something to do on the file. Other keys pass as they are. The listing (app badges) and the run check (authorise) both read the state through this, so the menu and the server agree.
func PinLength ¶ added in v0.54.0
PinLength is a `pin-input` node's length: its `length` prop clamped to 4..8, 6 when it names none. SanitizeSurface writes it back onto the node, so the browser draws the box this judge measures.
func SanitizeSurface ¶
SanitizeSurface prunes unknown node types, caps counts and depth.
func SetJobRoot ¶ added in v0.52.0
SetJobRoot stamps a confined caller's root into a job's params.
func SetOutputOverride ¶
SetOutputOverride stores o under the override key.
func StampJobRoot ¶ added in v0.52.0
StampJobRoot stamps a root as it was recorded (`<adapter>://<rel>`): the public page door's, whose job carries the root of the job that opened the link (model.Share.AppRoot). An empty spec stamps nothing - a link opened with no root - and one that does not read as a root confines the job to nothing when it runs (JobRoot).
func StripHostParams ¶ added in v0.48.0
StripHostParams is params without the host's own keys, never nil.
⚠⚠ runJob obeys these without asking again, so they may only carry what a door checked: the output-folder validation (the storage's tenant, the person's editor right there, filex's own folders) lives at submit. Every door that queues a job — the run request, a surface's job, a public page's job, a scheduled item — strips them first and then stamps only its own.
func TickTimeout ¶
TickTimeout is the clamped budget for one `tick` call: whatever the manifest asked for as a call timeout, never more than MaxTickTimeout.
func UIPolicy ¶ added in v0.48.0
UIPolicy is the Content-Security-Policy and the Connection-Allowlist an interface's HTML is served with. `pkg` is <P>: the explicit origin and version path the interface is served from, ending in "/" (https://files.example.com/_appui/drawio/3f9a0c1e5b2d4f60/). `grants` is what the administrator approved — the ONLY source of exceptions.
func ValidOutputMode ¶
ValidOutputMode is the closed set an Output.Mode may take. `folder` is a per-job choice only (a manifest declares `sibling` + `elsewhere`).
func ValidScheduleKey ¶
ValidScheduleKey reports whether an app may use key for a scheduled item.
func ValueString ¶ added in v0.54.0
ValueString is JavaScript's `String(v)` for the shapes JSON can produce — how the browser spells a value it compares (an option, a condition). ⚠ A number arrives as float64 through encoding/json, and `%v` would print a round million as `1e+06`; `strconv` with precision -1 gives the browser's own spelling back.
func WithActorIP ¶
WithActorIP carries the address a signed-in person's request came from into a view call, where it becomes `context.actor.ip` (wire.Actor.IP). The handler knows the request (and the trusted-proxy rule that reads it); the registry does not, and should not have to.
Types ¶
type ActionRow ¶
type ActionRow struct {
Plugin string `json:"plugin"`
ID string `json:"id"`
Key string `json:"key"`
Label wire.Text `json:"label"`
Icon string `json:"icon,omitempty"`
Applies wire.Applies `json:"applies"`
View string `json:"view,omitempty"`
// ViewPlacement is the declared placement of View (modal | page), so
// the menu knows whether to open a dialog or a new tab.
ViewPlacement string `json:"view_placement,omitempty"`
Confirm wire.Text `json:"confirm,omitempty"`
MinRole string `json:"min_role,omitempty"`
Danger bool `json:"danger,omitempty"`
OutputMode string `json:"output_mode"`
// OutputElsewhere: the result may go into a folder the person chooses
// (manifest output.elsewhere), so the action is offered on a read-only
// storage too — its screen asks where the result should go.
OutputElsewhere bool `json:"output_elsewhere,omitempty"`
// ReadOnlyOK is the server's answer to "does the menu offer this action
// on a file of a read-only storage?" (OffersOnReadOnly): the same rule
// the run applies (handlers authorise), sent with the row so the menu
// shows exactly what a click would be let do. Always sent.
ReadOnlyOK bool `json:"read_only_ok"`
// Gated is what the action WOULD also be offered on once a requirement
// the server lacks is met — the extensions LibreOffice would add to the
// signing app's "Sign…", say. Sent to administrators only: the owner's
// rule for anything that depends on how the server is set up is "greyed
// with the reason for an administrator, not shown to anybody else", so
// the explorer draws each as a disabled row that says what is missing.
Gated []GatedRule `json:"gated,omitempty"`
// UI: the action opens the app's own interface (its view has a `ui`
// file) — the explorer draws the frame; nothing is queued.
UI *UIRef `json:"ui,omitempty"`
// Requires is the app's user permission the action needs
// (app.<app>.<id>, perm/app.go), empty for none; RequiresDefault is who
// holds it until decided. The list handler drops what the caller does
// not hold, so the menu never offers what the run would refuse.
Requires string `json:"requires,omitempty"`
RequiresDefault string `json:"-"`
}
ActionRow is one menu entry as GET /api/files/plugins/actions returns it.
type ActionsAnswer ¶
type ActionsAnswer struct {
Actions []ActionRow `json:"actions"`
Views []ViewRow `json:"views"`
// OpenRules are the administrator's rules for which handler opens a kind
// of file (internal/assoc, capability open), by kind: the order handlers
// are offered in and the ones switched off. A kind without a rule keeps
// the default order - the apps' viewers, then filex's own. The explorer
// applies them exactly as assoc.Apply does (packages/core lib/appViewer).
OpenRules map[string]assoc.Rule `json:"open_rules,omitempty"`
}
ActionsAnswer is the whole list for one caller.
type AppClock ¶ added in v0.54.0
type AppClock struct {
// contains filtered or unexported fields
}
AppClock is the apps' view of the time: the real clock moved by a fixed offset. The zero value is the real clock.
func AppClockAt ¶ added in v0.54.0
AppClockAt is the clock that reads at when the real clock reads now.
func AppClockFromEnv ¶ added in v0.54.0
AppClockFromEnv reads EnvAppClock. Unset or empty is the real clock; a value that is not an RFC 3339 instant is an error, and the caller keeps the real clock rather than guessing.
func (AppClock) FromApp ¶ added in v0.54.0
FromApp moves an instant an app named back onto the real clock.
type AppNewDocument ¶ added in v0.48.0
type AppNewDocument struct {
Key string `json:"key"`
Plugin string `json:"plugin"`
View string `json:"view"`
Ext string `json:"ext"`
Label wire.Text `json:"label"`
Mime string `json:"mime"`
Template bool `json:"template"`
}
AppNewDocument is one row an app adds to the "New" menu, as the explorer is told it. Key is what a create request names (`app:<plugin>:<ext>`).
type AutoUpdated ¶ added in v0.47.0
type AutoUpdated struct {
From string `json:"from"`
To string `json:"to"`
At time.Time `json:"at"`
}
AutoUpdated is one automatic update: from which version, to which, when.
type CAList ¶
type CAList struct {
ID string `json:"id"`
Subject string `json:"subject"`
Issuer string `json:"issuer"`
Fingerprint string `json:"fingerprint"`
Imported bool `json:"imported"`
NotBefore time.Time `json:"not_before"`
NotAfter time.Time `json:"not_after"`
CreatedAt time.Time `json:"created_at"`
RetiredAt *time.Time `json:"retired_at,omitempty"`
Live bool `json:"live"`
}
CAList describes one signing authority for the admin surface.
type CANote ¶ added in v0.50.0
CANote is something an operator should know about an authority they imported. It is said at import (the answer's `warnings`, and the log); it never refuses the import - the authority is theirs to choose.
func ImportNotes ¶ added in v0.50.0
ImportNotes says what importing the authority in certPEM means beyond "it can sign" (CANote); nil when there is nothing to say or it does not parse.
type CallError ¶
type CallError struct {
Code string
Export string
Message string // safe for a user; the guest's own words when it set any
Cause error // the runtime's error, for the plugin log only
}
CallError is a failed guest call, classified.
type Cataloguer ¶
type Cataloguer interface {
Catalogue(ctx context.Context, storageID int64, rel string) (*model.Node, error)
}
Cataloguer records in the catalogue a file the STORAGE has and the catalogue has not seen yet, with the same bookkeeping a write through filex gets (node row, parent rows, index, thumbnail), and answers its node.
The output sink implements it (handlers.AppPlugins, through protocolsync); it is a separate interface so a sink that does not — every test double of OutputSink — leaves share_create exactly as strict as it was.
type Compat ¶ added in v0.47.0
type Compat struct {
Requires string `json:"requires"`
OK bool `json:"ok"`
Filex string `json:"filex"`
// Message is the install review's sentence for a range that leaves this
// filex out, in the reader's language (Said); empty on a list row and
// on a range this filex is in. The wizard prints it as it came.
Message string `json:"message,omitempty"`
}
Compat is what the Apps screens say about an app's range: the range as written, whether the running filex is in it, and which filex that is. Absent when the manifest names none.
func (*Compat) Said ¶ added in v0.55.0
Said fills Message for the review of name at version, in lang, when the range leaves this filex out (server.install.review_incompatible), and answers c. ⚠ The sentence is the server's: the wizard used to build it from requires and filex with a copy of its own (0.55).
type Compiled ¶
type Compiled struct {
Name string
Manifest *Manifest
SHA256 string
// contains filtered or unexported fields
}
Compiled is one installed plugin's module, compiled once and instantiated per call.
func (*Compiled) Call ¶
func (c *Compiled) Call(ctx context.Context, export string, input []byte, budget time.Duration) ([]byte, error)
Call runs one export on a fresh instance with a wall-clock budget. The returned bytes are the guest's output. Errors are *CallError.
ctx may carry a call scope (WithScope) that host functions read to decide what this particular call is allowed to touch; the guest never sees it.
func (*Compiled) Describe ¶
Describe calls the guest's describe export and checks that it agrees with the installed manifest on the things a grant depends on. The file on disk is the operator's intent; the guest's answer is the proof it is the same program.
type DryRunAnswer ¶
type DryRunAnswer struct {
Manifest *wire.Manifest `json:"manifest"`
Permissions []PermissionRow `json:"permissions"`
// WasmSHA256 / WasmBytes describe the module; both empty for a language
// pack, which has none (ManifestSHA256 is what was verified instead).
WasmSHA256 string `json:"wasm_sha256"`
WasmBytes int64 `json:"wasm_bytes"`
Signed bool `json:"signed"`
// Kind: KindApp | KindLanguagePack. The review says which BEFORE the
// install, so an administrator is not asked to trust a module that is
// not there, or surprised by one that is.
Kind string `json:"kind"`
ManifestSHA256 string `json:"manifest_sha256,omitempty"`
// Languages: what the app would add to filex itself — coverage of the
// current catalogue, and whether each is written right to left.
Languages []LanguageRow `json:"languages,omitempty"`
// Installed is the app of the same name already on this server (an
// install cannot proceed; an upgrade of it can). Nil on an upgrade's own
// dry run, and when nothing of that name is installed.
Installed *DryRunInstalled `json:"installed,omitempty"`
// EnginesMissing are the engines the manifest asks for that this server
// does not have: the app installs, and whatever needs them will not work.
EnginesMissing []DryRunEngine `json:"engines_missing,omitempty"`
// Compat is the manifest's `filex` range judged against this filex
// (compat.go); absent when it names none. `ok: false` is said HERE, at
// the review, and the install or upgrade itself answers `incompatible`.
Compat *Compat `json:"compat,omitempty"`
// Upgrade is what an upgrade's review shows on top of an install's: the
// version it replaces and how the grant changes. Nil on an install.
Upgrade *DryRunUpgrade `json:"upgrade,omitempty"`
// Engine: the app brings a WebAssembly module (false: a language pack, or
// an app that is only an interface).
Engine bool `json:"engine"`
// UI is the app's own interface: the bundle, its script-policy
// exceptions, and every external address — mirrored or live. The review
// draws it as its own group, with what a live address means.
UI *UIInfo `json:"ui,omitempty"`
// FileTypes are the kinds the app would open or draw thumbnails of, each
// with who handles it now and where the app lands by default - the
// review's File types group (internal/assoc, filled by the HTTP layer).
FileTypes []assoc.InstallKind `json:"file_types,omitempty"`
}
DryRunAnswer is what a dry run returns for the review step.
⚠ Installed and EnginesMissing are said HERE, at the review, because the dry run already knows them. Before, reinstalling an app that was already there passed the review and only "Install" answered "an app with this name is already installed", and an app needing an engine this server lacks was reviewed as if it would work (release-candidate sweep, 2026-09-21).
type DryRunEngine ¶
type DryRunEngine struct {
ID string `json:"id"`
Name string `json:"name"`
// Kind is DryRunEngineOffice for the office engine, which is a document
// server to connect rather than a program to install (and needs no
// restart once connected); empty for a binary engine.
Kind string `json:"kind,omitempty"`
}
DryRunEngine is one engine by its id and by the name a person reads.
type DryRunInstalled ¶
DryRunInstalled names the installed app a new install would collide with.
type DryRunUpgrade ¶ added in v0.47.0
type DryRunUpgrade struct {
From string `json:"from"`
Added []string `json:"added,omitempty"`
Removed []string `json:"removed,omitempty"`
AddsModule bool `json:"adds_module,omitempty"`
// What else the version changes, for the review (upgradeReview): the
// module (its hash), the interface (added, removed, its files), the filex
// range, the signature, and the source's own notes. The approval rule
// itself is Added/AddsModule and nothing else.
ModuleFrom string `json:"module_from,omitempty"`
ModuleTo string `json:"module_to,omitempty"`
UIFrom string `json:"ui_from,omitempty"`
UITo string `json:"ui_to,omitempty"`
UIFiles *UIFileDiff `json:"ui_files,omitempty"`
FilexFrom string `json:"filex_from,omitempty"`
FilexTo string `json:"filex_to,omitempty"`
SignedFrom bool `json:"signed_from"`
SignedTo bool `json:"signed_to"`
Notes string `json:"notes,omitempty"`
}
DryRunUpgrade is the jump an upgrade makes. Added are the permissions the new version asks for that the installed one was not granted — what the administrator is asked to approve; Removed are the ones it no longer asks for (the grant narrows by itself). AddsModule: a language pack that now brings a module — code that runs, where there was none.
type FieldProblem ¶ added in v0.54.0
type FieldProblem struct {
// Key is where the answer sits: a form field's key, a node's id, or
// `<node id>.<box id>` for one box of a `pdf-fields` node — the key the
// screen marks (surface.errors) and a refusal names (`fields`).
Key string `json:"key"`
Code string `json:"reason"`
// Limit is the bound that was broken (min, max, a code's length, a
// rule's length); 0 when the reason has none.
Limit int `json:"limit,omitempty"`
}
FieldProblem is why one answer was refused.
func CheckFieldValue ¶ added in v0.54.0
func CheckFieldValue(f wire.Field, v any) *FieldProblem
CheckFieldValue judges one answer against the Field that asked for it, by its type: `int` is a whole number inside min..max, `bool` is yes or no, `select` holds one of the options (each of them, for `multi`), and every other type (string, password, text, date) holds text. An unanswered value always fits here.
⚠ Lenient about SPELLING, strict about meaning: a whole number may arrive as `5` or `"5"` and a bool as `true` or `"true"`, because a plugin's own `default` reaches the browser and comes back exactly as the plugin wrote it — refusing an app's own default would refuse the app. What is refused is a value the field could never hold: `1.5` or `"abc"` for an int, a list for a text box, an option the screen did not offer.
func CheckPin ¶ added in v0.54.0
func CheckPin(id string, length int, v any) *FieldProblem
CheckPin judges a `pin-input`'s answer: text of exactly the node's length with no space in it. An unanswered code fits (whether one is needed is the app's question).
func CheckSetting ¶ added in v0.54.0
func CheckSetting(f wire.Field, v string) *FieldProblem
CheckSetting is CheckFieldValue for a stored setting, which is always a string on the wire (the admin panel joins a multi select with commas), plus the one rule a setting has that a form field leaves to the conditions: a `required` field may not be saved empty. A field whose requirement depends on another (`show_when`, `required_when`) is not demanded here — the settings screen decides whether it is on screen.
func JudgePdfFill ¶ added in v0.54.0
JudgePdfFill judges what a `pdf-fields` node in `fill` mode sent back (`{fields: [{id, value, font?}]}`) and rewrites it to what the app may trust:
- only boxes on THIS screen that belong to THIS signer stay (a box with no assignee is anybody's) — a box of another signer, or one the screen never drew, is dropped, the same way a hidden field's value is: a signer cannot fill in a box they were not shown;
- each box's value has its type's shape (a tick is a bool, a date is YYYY-MM-DD, everything else text) and a text box obeys its rule;
- `label` and `rule` are the node's own, never the client's: the app stamps and audits from this array alone, and a label the signer could choose is an audit trail the signer could write.
A value that breaks a rule refuses the event: the problems name the boxes (`<node id>.<box id>`), or the node itself when its answer is not the shape fill mode sends. A node that sent nothing (nil) stays nothing.
func (FieldProblem) Say ¶ added in v0.54.0
func (p FieldProblem) Say(lang string) string
Say is the problem in the reader's language.
type GitHubInput ¶
type GitHubInput struct {
Repo string `json:"github_repo"`
Ref string `json:"ref"`
// Commit (a store link's; never the API's): the manifest and every file
// the repository serves are read at this commit, not at the tag, which
// may have moved since the store approved it. `{tag}` in an address still
// stands for Ref (a release asset is the tag's).
Commit string `json:"-"`
}
GitHubInput is the JSON body of a GitHub install.
type Grants ¶
type Grants map[Permission]bool
Grants is the set an administrator approved.
func NewGrants ¶
func NewGrants(perms []Permission) Grants
NewGrants builds a set from validated permissions.
func (Grants) AllowedHosts ¶
AllowedHosts lists the http:* grants as Extism allowed_hosts patterns.
func (Grants) Has ¶
func (g Grants) Has(p Permission) bool
Has answers a permission. An engine is granted under either of its names (sameEngineGrant).
func (Grants) HasHost ¶
HasHost answers whether an outbound HTTP request to host is allowed: an exact "http:host" grant, or a "http:*.domain" grant covering a subdomain.
func (Grants) Missing ¶
func (g Grants) Missing(want []Permission) []Permission
Missing returns the permissions in want that are not in g — what an upgrade must ask the administrator to approve again.
type HostFunc ¶
type HostFunc = extism.HostFunction
HostFunc is a host function the runtime links into every instance. The registry builds them (hostfn.go); tests pass a few of their own.
type InstallError ¶
type InstallError struct {
Code string
Message string
Missing []string
Reason string // a FetchReason* for fetch_failed, else ""
Where string // the repository or the URL that was being fetched
Refs []string // the refs a repository install tried
Status int // the HTTP status that came back, when one did
// Requires and Filex narrow an `incompatible`: the range the manifest
// declares and the filex it leaves out (compat.go).
Requires string
Filex string
}
InstallError is a failure caused by what the caller supplied. Code is what the HTTP layer answers; Missing carries the permission diff for permissions_incomplete / permissions_changed.
Reason, Where, Refs and Status narrow a fetch_failed, so the install wizard can write a sentence in the reader's language that says WHAT to check. ⚠ The message alone used to be the answer: "filex-app.json not found in BRF-Tech/yok-boyle-bir-depo: http 404 from raw.githubusercontent.com", English, in the Turkish wizard (release-candidate sweep, 2026-09-21).
func (*InstallError) Error ¶
func (e *InstallError) Error() string
type InstallInput ¶
type InstallInput struct {
Manifest []byte
// Wasm is the module; Reader is consumed, capped at MaxWasmBytes.
Wasm io.Reader
// UI is the interface bundle (a zip) when the manifest has a `ui` block;
// consumed, capped at MaxUIBytes.
UI io.Reader
// SHA256 (lower hex) the module must match; "" skips (upload only).
SHA256 string
Signature string
Source string
SourceURL string
// ManifestURL is where a URL install read the manifest — what the update
// check re-reads (SourceURL is the module's address for an app).
ManifestURL string
// Pinned: the administrator gave the SHA-256 themselves (a URL install).
// "Exactly these bytes" is not something an automatic update may
// overrule, so such an install starts with automatic updates off.
Pinned bool
// Granted is the permission list the admin approved. It must equal the
// manifest's set exactly.
Granted []string
DryRun bool
Lang string
// ActorID is the administrator who approved this (the audit row names
// them); nil for the system.
ActorID *int64
// Rollback: this is "Back to <version>" (versions.go) — the kept files,
// under the grant they ran with.
Rollback bool
// UIPin pins the interface bundle when the manifest does not (a kept
// version is held to the hash recorded when it was replaced).
UIPin string
// Mirrors are mirrored external files already at hand, by sha256 (a kept
// version's): used instead of downloading them again.
Mirrors map[string][]byte
// Notes are the source's release notes for this version, as plain text,
// for the review (a GitHub release's body).
Notes string
// Placements are the administrator's choices at the review's File types
// group: where the new app goes for each kind it opens or draws
// (internal/assoc). The registry does not read them; the HTTP layer
// writes them once the app is installed and running.
Placements []assoc.Placement
}
InstallInput is one install or upgrade request after the HTTP layer has gathered the pieces.
type InstallRefusal ¶ added in v0.47.0
type InstallRefusal struct {
Code string `json:"error"`
Message string `json:"message,omitempty"`
Missing []string `json:"missing,omitempty"`
Reason string `json:"reason,omitempty"`
Where string `json:"where,omitempty"`
Refs []string `json:"refs,omitempty"`
Status int `json:"status,omitempty"`
Requires string `json:"requires,omitempty"`
Filex string `json:"filex,omitempty"`
// Detail is the server's English behind Message once the refusal is
// said to a reader (Said): Message is then the reader's sentence.
// Empty on a stored refusal, whose Message is still the English.
Detail string `json:"detail,omitempty"`
}
InstallRefusal is an InstallError as the wire carries it — the body of a refused install (handlers.installErrorBody) and the reason an update check or an automatic update stopped. One shape, so the panel explains both with the same sentences.
func RefusalOf ¶ added in v0.47.0
func RefusalOf(err error) *InstallRefusal
RefusalOf is err as the panel reads it.
func (*InstallRefusal) Said ¶ added in v0.55.0
func (ref *InstallRefusal) Said(lang string) *InstallRefusal
Said is the refusal as a reader is told it: `message` is the server's sentence for its code in lang (`server.install.<code>`, a failed download's `server.install.fetch.<reason>`), filled from its own fields, and Go's English moves to `detail`, for a log. A copy: what an update check stored (UpdateInfo.Refusal) keeps its English and is said again, in the language of whoever reads it, every time it is read.
⚠⚠ Why (0.55, the 0.54 rule "the server writes the sentence"). The install wizard and the Apps list built this sentence in the browser (web lib/appPluginRefusal.ts with appPlugins.wizard.errors.*), from the code and the fields; the command line and an agent read Go's English. Said twice (a refusal already said) it is returned as it is.
type Installed ¶
type Installed struct {
Row *model.AppPlugin
Manifest *Manifest
Grants Grants
// Perms is the grant as a sorted list, for answers.
Perms []Permission
// contains filtered or unexported fields
}
Installed is one plugin's live entry.
func (*Installed) HasModule ¶ added in v0.48.0
HasModule reports whether the app runs a wasm module: every app but a language pack and an app that is only an interface (its row has no module file).
func (*Installed) State ¶
State returns the live state and its error. A running app whose license does not hold is StateUnlicensed, with the license's reason: every caller that runs an app asks for StateRunning, so a held app runs nothing.
type Item ¶
type Item struct {
Kind string // file | dir
Ext string // lower-case, no dot
Mime string
// State is the set of state keys the plugin under consideration keeps
// on this item (bare keys). Filled per plugin by the caller.
State []string
}
Item is what Matches sees of a selected entry.
type JobOpen ¶ added in v0.50.0
JobOpen is the screen a finished job asked for on one of its outputs: an action or a view of the app that ran it, or neither (just open the file).
type JobOutput ¶
type JobOutput struct {
Path string `json:"path"`
// Open marks the output the finished job sends its person to, and the
// app's own screen to start there (openAfter). At most one output of a
// job carries it; kept in the job row's outputs, so no column of its own.
Open *JobOpen `json:"open,omitempty"`
}
JobOutput is one committed output, as the ops row reports it.
type JobQueue ¶
type JobQueue interface {
SubmitTo(ctx context.Context, kind string, storageID, destStorageID int64, sources []string, dest string) (*ops.Op, error)
}
JobQueue is the ops queue, as the scheduler needs it: a way to hand an app_plugin_jobs row to the same worker a person's job goes through. *ops.Service satisfies it; the server injects it with SetJobQueue.
Without it a due item fails loudly (status `failed`, the reason on the row) rather than disappearing.
type LanguageRow ¶
type LanguageRow struct {
Code string `json:"code"`
// Keys the pack carries for this language (empty values not counted).
Keys int `json:"keys"`
// Translated is how many of those the current catalogue has; Unknown is
// the rest — keys filex no longer has, or never had (typos). Both are
// only meaningful when Total > 0.
Translated int `json:"translated"`
Unknown int `json:"unknown"`
// Total is the size of the current catalogue; 0 means this binary was
// built without one (a development build), and coverage is unknown.
Total int `json:"total"`
// Percent is floor(100 × Translated / Total): 100 only when nothing is
// missing, so "100 %" is never a rounding of "almost".
Percent int `json:"percent"`
// RTL: a right-to-left language (wire.IsRTL) — the interface is laid out
// right to left in it.
RTL bool `json:"rtl"`
}
LanguageRow is one language an app adds, as the Apps screens show it.
⚠ Coverage is measured against the CURRENT catalogue — the one this very binary's interface draws from — not against whatever the pack's author had when they wrote it. A pack written for v0.43 and run on v0.45 says how much of v0.45 it covers, and every string it lacks falls back to English.
type LogLine ¶
LogLine is one entry of a plugin's log: what the guest logged through pdk.Log plus the host's own warnings about it (refused calls, failed loads). The admin panel polls it with ?after=<seq>.
The log is internal/pluginlog, the one the storage plugins' page reads too (issue #104): a line repeated within the last 50 is counted on the line already there (`count`, `last`) instead of written again.
type Manifest ¶
type Manifest struct {
wire.Manifest
// Perms is Permissions parsed and validated, followed by the permissions
// the `ui` block derives (uimanifest.go).
Perms []Permission
// contains filtered or unexported fields
}
Manifest is a validated filex-app.json.
func ParseManifest ¶
ParseManifest decodes and validates a manifest document.
func ParseManifestForReview ¶ added in v0.50.0
ParseManifestForReview is ParseManifest for a caller outside the package that holds a dry run's manifest (wire) and wants the handlers it adds.
func (*Manifest) CallTimeout ¶
CallTimeout is the clamped per-call budget for describe/view/page calls.
func (*Manifest) MemoryPages ¶
MemoryPages is the clamped wasm memory ceiling.
func (*Manifest) NeedsModule ¶ added in v0.48.0
NeedsModule reports whether anything the manifest declares runs a module: an action that does not just open an interface, a view the module draws, a public page, or a permission only a module can use. A manifest with an interface and none of these may install without a module (an app that is ONLY an interface, like draw.io's editor). A language pack never needs one.
func (*Manifest) UIViews ¶ added in v0.48.0
UIViews is every view of m that the interface draws, by id.
func (*Manifest) UserPermission ¶ added in v0.49.0
func (m *Manifest) UserPermission(id string) (wire.UserPermission, bool)
UserPermission returns the declared user permission id (manifest `user_permissions`), and whether there is one.
func (*Manifest) WritesElsewhere ¶
WritesElsewhere reports whether any action may put its result into a folder the person chooses (output.elsewhere) — what makes the host tell the app where that person's results go by default (CallContext.Home).
type Need ¶
Need is a requirement the server does not meet: `kind` says which sort ("engine" today), `id` the machine's word, `name` the one a person reads.
type OfficeConverter ¶ added in v0.50.0
type OfficeConverter interface {
// Ready reports whether a document server is configured right now. It is
// read on every availability question, so it must be cheap (no network).
Ready(ctx context.Context) bool
// Convert turns one file into another format and writes the result to
// req.Dst. A refusal by the document server is an *OfficeError; no server
// configured is ErrOfficeUnconfigured; a result over req.MaxBytes is
// ErrOfficeTooLarge. Nothing is left at req.Dst on any error.
Convert(ctx context.Context, req OfficeRequest) error
}
OfficeConverter is the office engine's back end: the connected document server (wired by the server from internal/onlyoffice; a fake in tests).
type OfficeError ¶ added in v0.50.0
OfficeError is the document server failing or refusing a conversion. Code is the conversion API's error (-1 … -10), 0 when it gave none (the result could not be fetched, say); Reason is English, for the log.
func (*OfficeError) Error ¶ added in v0.50.0
func (e *OfficeError) Error() string
type OfficeRequest ¶ added in v0.50.0
type OfficeRequest struct {
// Src is the input on this machine (inside the run directory); Name is
// its file name, which the document server is told as the title.
Src string
Name string
// From is the input's format (its extension, lower case, no dot); To is
// the conversion API's output type: an extension, or "pdfa".
From string
To string
// Delimiter and CodePage are the conversion API's CSV knobs (0 = not
// said: the document server's default).
Delimiter int
CodePage int
// Dst is where the result goes; MaxBytes its ceiling (0 = none).
Dst string
MaxBytes int64
}
OfficeRequest is one conversion.
type Options ¶
type Options struct {
Store db.Store
// a share (migration 00046), so it goes through the same service every
// other link does and inherits the instance's expiry ceiling, the PIN
// gate and the administrator's revoke. nil refuses share_create.
Share *share.Service
// Dir is where modules live; the compilation cache and the call spool
// sit next to it.
Dir string
// SecretKey seals secret settings (secretbox). Empty → secret fields are
// refused at PutSettings rather than stored in the clear.
SecretKey string
// TrustedKeys (hex/base64 ed25519) make a detached signature mandatory.
TrustedKeys []string
// Demo refuses every install/upgrade (the admin account is public).
Demo bool
// HTTP fetches manifests, modules and interface bundles - an
// administrator's install, an install request, the update check. Nil (what
// a server passes) is the shared guarded download client
// (netguard.DownloadClient): public addresses only, after DNS and on every
// redirect hop, no redirect from https to plain http, 5 hops at most.
// Supplying a client lifts that guard; it exists for tests and for an
// embedder with an egress policy of its own.
HTTP *http.Client
// LoopbackSources lets the guarded client reach this machine
// (FILEX_PLUGIN_LOOPBACK_SOURCES): development and the end-to-end tests
// serve app sources from a loopback server. Never the private network.
LoopbackSources bool
// GitHubRawBase is where a repository's files are read from for a GitHub
// install (FILEX_APP_GITHUB_RAW_BASE): "" is https://raw.githubusercontent.com.
// A mirror of it (an air-gapped install's), or the end-to-end tests' fake
// GitHub. The download guard applies to it like to every other address.
GitHubRawBase string
Log *slog.Logger
// StorageResolver opens the driver a job reads from and writes to.
StorageResolver func(int64) (storage.Driver, error)
// Limits (bytes). Zero → defaults below.
MaxWasmBytes int64
MaxInputBytes int64
MaxOutputBytes int64
// MaxUIBytes caps an interface bundle, zipped (FILEX_APP_PLUGIN_MAX_UI_MB).
MaxUIBytes int64
// PerPluginJobs bounds concurrent action_run calls per plugin (default 2).
PerPluginJobs int
// PerPluginCalls bounds concurrent SCREEN calls per plugin — view and
// public page events (default 8). Each is a fresh instance with up to
// the manifest's memory ceiling (256 MiB at most), and a public page
// event is answered for an anonymous visitor: without a ceiling, a burst
// of events on one link held that much memory per request.
PerPluginCalls int
// Office is the office engine (`engines:office`, alias
// `engines:libreoffice`): the connected OnlyOffice Document Server's
// conversion API (office.go). Nil = no office engine on this server.
Office OfficeConverter
// Clock is the apps' clock (appclock.go). The zero value reads
// FILEX_APP_CLOCK, and with that unset it is the real clock. ⚠
// Screenshots and tests only: an app on a moved clock dates its
// signatures and reminders with a time that is not now.
Clock AppClock
}
Options configures the registry.
type OutputSink ¶
type OutputSink interface {
// CommitSibling writes a NEW file next to the first input, taking a
// unique name when the preferred one is taken. Returns the final path.
CommitSibling(ctx context.Context, storageID int64, dir, name string, r io.Reader, size int64, actor *int64) (string, error)
// CommitVersion overwrites rel in place (the previous bytes become a
// version when versioning is on).
CommitVersion(ctx context.Context, storageID int64, rel string, r io.Reader, size int64, actor *int64) error
}
OutputSink lands a finished output on a storage with filex's own bookkeeping (kind guard, version snapshot on overwrite, node row, index, thumbnail, write hook, change frame). Implemented by the HTTP layer, which owns those services; the registry only decides WHAT to write WHERE.
type OverrideRow ¶
type OverrideRow struct {
ID string `json:"id"`
Enabled bool `json:"enabled"`
AdminOnly bool `json:"admin_only"`
Applies *wire.Applies `json:"applies"`
}
OverrideRow is the admin API shape of one action override. Applies is a WHOLE rule both ways — the editor shows a list and sends a list — while the row stores only what changed against the manifest (applies_override.go says why). Nil = as the manifest says.
type PageFile ¶
type PageFile struct {
Ref string `json:"ref"`
Name string `json:"name"`
File string `json:"file"`
Size int64 `json:"size"`
Mime string `json:"mime,omitempty"`
}
PageFile is one exposed copy, as files_json stores it.
⚠ `File` is a BASENAME inside the share's own directory, not an absolute path. v2 stored the absolute path, so moving or restoring the data directory silently broke every exposed copy while the row looked healthy.
type PageInfo ¶
type PageInfo struct {
Plugin string `json:"plugin"`
Page string `json:"page"`
Title wire.Text `json:"title"`
Subject string `json:"subject,omitempty"`
RequiresPIN bool `json:"requires_pin"`
Unlocked bool `json:"unlocked"`
ExpiresAt *time.Time `json:"expires_at,omitempty"`
Files []wire.FileRef `json:"files"`
}
PageInfo describes an app link without opening it.
type PdfRule ¶ added in v0.54.0
type PdfRule struct {
Kind string `json:"kind"`
Min int `json:"min,omitempty"`
Max int `json:"max,omitempty"`
}
PdfRule is what a `text` box on a PDF accepts (a `pdf-fields` box's `rule`): `any`, `number` or `email`, and a length in characters.
func NormalizePdfRule ¶ added in v0.54.0
NormalizePdfRule reads a box's `rule`; nil when it says nothing. An unknown kind reads as `any` — including the older `date` rule, which v3 made a box TYPE: the box keeps taking text rather than refusing every signer of an older document. A bound that is not a positive whole number is no bound.
type Permission ¶
type Permission string
Permission is one capability a plugin asks for in its manifest and an administrator grants at install. The set is CLOSED: a manifest naming a permission this host does not know is refused at install, because a grant the admin cannot read is not a grant.
Two shapes: bare names ("files:read") and parameterised ones ("http:api.example.com", "engines:ffmpeg"). The parameter is part of the permission — granting "http:a.example.com" says nothing about b.example.com.
const ( PermFilesRead Permission = "files:read" PermFilesWrite Permission = "files:write" PermFilesLock Permission = "files:lock" PermSign Permission = "sign" PermMailSend Permission = "mail:send" PermNotifySend Permission = "notify:send" PermUsersLookup Permission = "users:lookup" PermSettings Permission = "settings" PermState Permission = "state" PermPublicPages Permission = "public_pages" // PermSchedule is the one permission that makes an app run when nobody // asked it to: it is woken once an hour and runs the work it scheduled // at the minute it named. An app without it is never woken, and there // is no other way in — see schedule.go. PermSchedule Permission = "schedule" // The interface's own permissions (uiperm.go) — DERIVED from the // manifest's `ui` block, never listed in `permissions`: `ui` for having // an interface at all, `ui:eval` / `ui:wasm-eval` for its script-policy // exceptions. Live addresses are `ui-net:<as>:<url>`. PermUI Permission = "ui" PermUIEval Permission = "ui:eval" PermUIWasmEval Permission = "ui:wasm-eval" // PermUIPackageFetch: the interface reads its own package — this // version's files, nothing else (`ui.package_fetch`). PermUIPackageFetch Permission = "ui:package-fetch" // PermUIDownload: the interface hands the person files to keep on their // own disk, each time with their say (`ui.download`). PermUIDownload Permission = "ui:download" // PermUIFramePackage: the interface opens pages of its own package in // frames of its own — this version's pages only, each served under the // same policy and sandbox (`ui.frame_package`). An editor that puts its // document in a frame of its own (ONLYOFFICE's frameEditor) needs it. PermUIFramePackage Permission = "ui:frame-package" // PermUIConnectBlob: the interface reads `blob:` addresses it made // itself with fetch/XHR (`ui.connect_blob`) — memory of the page, never // a network address. PermUIConnectBlob Permission = "ui:connect-blob" // PermUIPrint: the interface hands filex a PDF and filex prints it from // its own page, each time with the person's say (`ui.print`): a // sandboxed frame may not open the browser's print dialog. The same // kind of grant as ui:download - the print dialog can save the PDF. PermUIPrint Permission = "ui:print" )
Bare permissions.
const PermFilesCoEdit Permission = "files:co-edit"
PermFilesCoEdit: the app's interface edits the files it opens together with other people, through filex's relay. Derived from `co_edit.open`, never listed in `permissions`.
const PermFilesE2EPlaintext Permission = "files:e2e-plaintext"
PermFilesE2EPlaintext: the app's interface is handed the plaintext of files in unlocked encrypted folders, decrypted in the person's browser, and what it saves is encrypted there again. Derived from `encrypted_folders.open`, never listed in `permissions`.
func ParsePermission ¶
func ParsePermission(s string) (Permission, error)
ParsePermission validates one manifest entry.
func UINetPermission ¶ added in v0.48.0
func UINetPermission(as, u string) Permission
UINetPermission is the permission a live address is: `ui-net:<as>:<url>`.
func (Permission) Label ¶
func (p Permission) Label(lang string) string
Label is the plain-language meaning shown at install, in lang — any language the server catalogue speaks, a language pack's included (keys `server.perm.*`, internal/srvtext). It serves the API (`GET /api/admin/ app-plugins/{id}` → permission review) and the CLI.
⚠ This is what an administrator reads before trusting an app with their files. It was English or Turkish — a Spanish administrator read the one screen that asks for consent in English, around a Spanish wizard. A key a pack lacks falls back to English, never to the permission id.
type PermissionRow ¶
type PermissionRow struct {
ID string `json:"id"`
Label string `json:"label"`
Reason wire.Text `json:"reason,omitempty"`
}
PermissionRow is one line of the install-time review.
func PermissionRows ¶
func PermissionRows(m *Manifest, lang string) []PermissionRow
PermissionRows renders the review for a manifest in lang.
type PreviousVersion ¶ added in v0.48.0
type PreviousVersion struct {
Version string `json:"version"`
ReplacedAt time.Time `json:"replaced_at"`
// Message says it in the reader's language, on the reader's clock
// (handlers sayStatus, 0.55).
Message string `json:"message,omitempty"`
// UI: the kept version has an interface of its own.
UI bool `json:"ui,omitempty"`
}
PreviousVersion is the kept version an administrator can go back to.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry is the installed set plus the runtime.
func (*Registry) ActionsFor ¶
ActionsFor lists what the caller may see: running plugins, enabled actions, admin-only ones only for admins.
func (*Registry) All ¶
All returns every entry, by name. (The languages the running apps add to filex itself — UILocaleList / UILocale — live in langpack.go.)
func (*Registry) AppLabel ¶
AppLabel is an installed app's own label, in every language its manifest wrote it in ({"en": "e-Signature", "tr": "e-İmza"}), or nil when no app of that name is installed here.
⚠ A lock, an action row and a job all carry the app's manifest NAME (`sign`), because that is what addresses it; a person reading "sign locked this file" is reading an identifier the rest of the product never shows them — every list, the install review and the app's own page say "e-Signature" (v0.43.0). So the words a person reads resolve the name to this, and fall back to the name only where the app is gone.
func (*Registry) AppLimits ¶ added in v0.50.0
AppLimits are an app's limits in force, for the pipeline's freshness rule (thumb.AppThumbs). ok is false for an app that draws nothing now.
func (*Registry) BackgroundUpdates ¶ added in v0.47.0
BackgroundUpdates reports whether the daily check runs.
func (*Registry) CACertPEM ¶
CACertPEM returns the tenant CA certificate (creating the CA on first use).
func (*Registry) CACertsPEM ¶
CACertsPEM returns EVERY certificate this tenant has ever signed with — the live CA first, then the retired ones, newest first — as one PEM bundle. This is the root set a verifier needs: a signature made two CAs ago must still check out, so nothing here is ever deleted.
func (*Registry) CAs ¶
CAs lists the tenant's signing authorities, live and retired, for the admin panel and the verify screen: who signed, with what, until when.
func (*Registry) CheckPIN ¶
CheckPIN verifies a PIN with the strike counter. A one-line forward: the gate itself is internal/share/pin.go, so /s/, /d/ and an app page cannot drift apart — which is exactly what v2 did (only the app page had a lock).
func (*Registry) CheckUpdates ¶ added in v0.47.0
func (r *Registry) CheckUpdates(ctx context.Context) (*UpdateReport, error)
CheckUpdates runs one check of every app that has a source and records what it found (it installs nothing) — or, when a check is already running, waits for that one and answers what it found. One at a time, whoever asks.
func (*Registry) Close ¶
Close frees every compiled module and the runtime. It waits for an upgrade in flight — an automatic one included — to finish its swap, and refuses any after it, so a shutdown never leaves an app half-replaced.
func (*Registry) DecorateOps ¶
DecorateOps fills the plugin fields of ops rows that are plugin jobs. DecorateOps fills the plugin columns of ops rows. A read failure is logged rather than swallowed: the row still renders, but as a nameless "plugin-action" with no message, which is how two different lost-update bugs stayed invisible.
func (*Registry) DrawThumbnail ¶ added in v0.50.0
func (r *Registry) DrawThumbnail(ctx context.Context, app string, req assoc.DrawRequest) ([]byte, error)
DrawThumbnail asks the app to draw one file: the bytes in req.Body, which must not be more than its size limit. It answers the image the app drew (a PNG or a JPEG, at most wire.ThumbnailMaxOutputBytes - the pipeline checks the rest), or an *assoc.DrawError.
func (*Registry) Engines ¶
Engines is the engine → can-run-now map for this host, every engine by its own id (the office engine as `office`, never its alias).
func (*Registry) FetchGitHub ¶
func (r *Registry) FetchGitHub(ctx context.Context, in GitHubInput) (*InstallInput, error)
FetchGitHub resolves a repository + ref into an InstallInput (manifest and module fetched, sha256 taken from the manifest unless overridden).
func (*Registry) FetchUpdate ¶ added in v0.47.0
FetchUpdate reads the newer version an app's source has — the one the update check announced — for an administrator's review and upgrade ("Review update" on the Apps list). The same search the check makes, so what is reviewed is what was announced; the decision is the administrator's.
func (*Registry) GitHubManifest ¶ added in v0.52.0
GitHubManifest reads filex-app.json from repo at ref.
func (*Registry) ImportCA ¶
func (r *Registry) ImportCA(ctx context.Context, tenantID int64, certPEM, keyPEM []byte) (*signingKey, error)
ImportCA takes over signing with an authority the operator already has — their own PKI, or a certificate they trust everywhere else. The current CA is retired, not deleted, so everything it signed keeps verifying.
certPEM may be a bundle: the signing certificate first, its issuers after it. keyPEM is that certificate's private key, in PKCS#8, PKCS#1 or SEC1 form, NOT encrypted — a .p12/.pfx is converted first (`openssl pkcs12 -in ca.p12 -nodes -out ca.pem`), because the encrypted forms in the wild are more varied than any one library reads.
func (*Registry) Install ¶
func (r *Registry) Install(ctx context.Context, in *InstallInput) (*Status, *DryRunAnswer, error)
Install stages, reviews and installs a plugin.
func (*Registry) InstanceID ¶
InstanceID is what this process writes into claimed_by.
func (*Registry) LanguageRows ¶
func (r *Registry) LanguageRows(m *Manifest) []LanguageRow
LanguageRows describes every language m adds, with its coverage. Nil-safe on the receiver (no catalogue → coverage unknown).
func (*Registry) LastUpdateCheck ¶ added in v0.47.0
LastUpdateCheck is when the last check ran; zero when never.
func (*Registry) LicenseHold ¶ added in v0.52.0
LicenseHold answers why app is held ("" = it is not).
func (*Registry) LinkHolds ¶ added in v0.53.0
func (r *Registry) LinkHolds(ctx context.Context, sh *model.Share, storageID int64, rel string) bool
LinkHolds reports whether rel on storageID - the link's document where it lies now (PageAnchor) - is inside the root the link recorded; true for a link opened with no root. It is the screen's own judgement (holdToLink, Scope.inOwnRoot), asked by the door that queues a visitor's job, so a document moved out of the root after the link was opened stops the submit there instead of in the worker (filex #185).
func (*Registry) LinkOf ¶
LinkOf says what an app's link IS, for a list of links (My shares, the admin's Shares): the purpose the app gave the link when it opened it, else the one its page declares, and the app's home view the row opens. Nil for an ordinary share, for an app that is gone, and for a link with no purpose — the row then lists as a plain share.
⚠ Page-less links too (an app's plain share of a file: PluginID set, no PageID). The finished document's delivery link listed as a share somebody made by hand, beside signing links marked as what they are.
func (*Registry) Load ¶
Load reads every row and compiles the enabled ones. A row that fails to load is kept (state failed/refused) so the admin sees why; it never stops the server.
func (*Registry) LoadPage ¶
LoadPage resolves a token to the live app share behind it (ErrPageNotFound / ErrPageGone).
⚠ A token that names an ordinary share is ErrPageNotFound here, not an error about kinds: this is an unauthenticated lookup and "wrong sort of link" is a fact about somebody else's data.
func (*Registry) LockReason ¶
LockReason is a lock's reason as words: the plain text (English, for a consumer with no reader — a log, a protocol server) and, for a reason the app named by message key, the same words in every language the app wrote them in. A plain reason has no Text; a message whose app or key is gone has no words at all (never the raw key).
func (*Registry) LookupUsers ¶
LookupUsers is the one directory search behind both the host function and the HTTP route. ctx must already carry the caller's tenant scope (the store is the tenant-scoped wrapper, which confines ListUsers by that scope).
func (*Registry) MaxOutputBytes ¶ added in v0.48.0
MaxOutputBytes is the ceiling on one file an app writes (a job's output, an interface's save).
func (*Registry) MaxUIBytes ¶ added in v0.48.0
MaxUIBytes is the interface bundle's ceiling, zipped.
func (*Registry) MintUnlock ¶
MintUnlock / VerifyUnlock forward to the same one implementation.
func (*Registry) NewDocument ¶ added in v0.48.0
func (r *Registry) NewDocument(key string) (AppNewDocument, bool)
NewDocument is the row a key names, when it is offered.
func (*Registry) NewDocumentBytes ¶ added in v0.48.0
NewDocumentBytes is what a new file of the row a key names starts as: the template from the app's package, or nothing. Refused for a row that is not offered (unknown, not granted, the app switched off).
func (*Registry) NewDocuments ¶ added in v0.48.0
func (r *Registry) NewDocuments() []AppNewDocument
NewDocuments is every row the running apps add to the "New" menu, app by app in name order and in each app's own order. A row is offered only while the app runs with its interface loaded, and only when the grant holds its kind (`ui-new:.<ext>`).
func (*Registry) OpenHandlers ¶ added in v0.50.0
func (r *Registry) OpenHandlers() []assoc.AppHandler
OpenHandlers lists the running apps' interfaces that open files (`viewer` views), by app name and then in the manifest's order - the open half of assoc.Source, and the order the explorer's list has always had.
func (*Registry) Overrides ¶
Overrides returns one row per manifest action, merged with stored changes.
func (*Registry) PageAnchor ¶
PageAnchor reports the storage and storage-relative path the link is about — what per-file state and the follow-up job hang on. Zero/"" when the node has gone.
func (*Registry) PageEvent ¶
func (r *Registry) PageEvent(ctx context.Context, sh *model.Share, p *Installed, in wire.ViewEventInput, visitorIP string) (*wire.Surface, error)
PageEvent runs the link's page_event export for an unlocked visitor. "open" spends one visit off the share's own counter. A surface carrying a job is returned as-is; the HTTP layer queues it as the share's creator.
func (*Registry) PutOverrides ¶
PutOverrides stores the rows (unknown and hidden action ids dropped, applies validated).
func (*Registry) PutSettings ¶
PutSettings stores values. A secret field sent as "***" keeps its current value; other secret values are sealed. Unknown keys are dropped.
⚠ Every value sent is judged against its manifest Field first (CheckSetting: type, options, min/max, a required field left empty) and the whole save is refused with a *SettingError naming the first field that does not fit — nothing is stored. The admin panel draws these fields with the same rules, but an API key or a crafted request never ran that screen, and an app reads its settings trusting the types its manifest declared.
func (*Registry) PutThumbLimits ¶ added in v0.50.0
func (r *Registry) PutThumbLimits(ctx context.Context, id int64, l ThumbLimits) (*ThumbLimitsAnswer, error)
PutThumbLimits stores an app's thumbnail limits (0 = the default). A value outside its range is refused with the field named, not clamped: what the administrator typed is what is stored or nothing is.
func (*Registry) RequiresSignature ¶
RequiresSignature reports whether installs must carry a signature.
func (*Registry) ResolveAction ¶
func (r *Registry) ResolveAction(ctx context.Context, plugin, action string, isAdmin bool) (*Installed, *wire.Action, wire.Applies, error)
ResolveAction finds a running plugin's enabled action for a run request. isAdmin gates admin-only actions. The error is a *CallError with CodeUnsupported (not running / disabled) or CodeRefused (admin only).
func (*Registry) Rollback ¶ added in v0.48.0
Rollback puts the kept version of an app back: its module, manifest, interface and mirrored files, under the grant it ran under — no new approval, because that grant was approved when it was installed. The version it replaces becomes the kept one, so the administrator can go forward again the same way. `by` is the administrator.
func (*Registry) RotateCA ¶
RotateCA retires the tenant CA; the next signature creates a fresh one. Leaves issued by the old CA stay verifiable through its certificate, which is why retiring never deletes.
func (*Registry) RunDueSchedule ¶
RunDueSchedule performs ONE pass: every row due at or before now, claimed and run. Exported so a test — and, later, an administrator's "run it now" — can drive the schedule without the loop.
A plugin that traps, panics or hangs takes down its own row and nothing else: each row runs behind a recover, and the call itself is bounded by the wasm runtime's own per-call budget.
func (*Registry) RunPluginAction ¶
func (r *Registry) RunPluginAction(ctx context.Context, op *ops.Op, live func(done, total int64)) error
RunPluginAction is what the ops worker calls for an OpPluginAction row. op.Dest carries the job id. Progress is fed to live so the tray can draw a bar; the job row records status, message and outputs.
func (*Registry) ScheduleOf ¶
func (r *Registry) ScheduleOf(ctx context.Context, id int64) ([]*model.AppPluginScheduleItem, error)
ScheduleOf returns one app's schedule rows, soonest first — what an admin screen would draw and what a test reads back.
func (*Registry) SetCatalogue ¶
SetCatalogue gives the registry the current string catalogue — every key of the explorer's and the admin panel's English tables — so the Apps screens can say how much of it a language covers.
⚠ Called with the keys of `admin/i18n/filex-catalogue-en.json`, which the web build writes (web/vite.config.ts → scripts/lib/i18n-catalogue.mjs) and the binary embeds. A binary built without the web build has none, and coverage then reads "unknown" rather than a made-up percentage.
func (*Registry) SetEnabled ¶
SetEnabled flips a plugin on or off, loading or unloading it.
func (*Registry) SetHTTPTransport ¶
func (r *Registry) SetHTTPTransport(t http.RoundTripper)
SetHTTPTransport replaces the transport http_request uses (tests).
func (*Registry) SetHeldPermissions ¶ added in v0.49.0
func (r *Registry) SetHeldPermissions(f func(ctx context.Context, u *model.User, p *Installed) []string)
SetHeldPermissions wires the answer to "which of this app's own user permissions does this person hold" (wire.Actor.Permissions) — the HTTP layer, which decides them at every door with the same question (handlers.appPermHeld), so what an app is told is what the door does.
func (*Registry) SetHomeResolver ¶
SetHomeResolver wires the answer to "where do this person's results go when not beside their source" (CallContext.Home) — the HTTP layer, which knows storages, tenants and the ACL.
func (*Registry) SetJobQueue ¶
SetJobQueue wires the queue scheduled work is handed to.
func (*Registry) SetLicenseHold ¶ added in v0.52.0
SetLicenseHold holds app (reason != "") or releases it (""). The hold is kept by name, so it outlives an upgrade (which replaces the entry) and applies to an app installed after it was set.
func (*Registry) SetMailer ¶
func (r *Registry) SetMailer(m mailSink)
SetMailer wires the mailer (nil → mail_send unavailable).
func (*Registry) SetNotify ¶
func (r *Registry) SetNotify(n notifySink)
SetNotify wires the notification service (nil → notify_send unavailable).
func (*Registry) SetOffice ¶ added in v0.50.0
func (r *Registry) SetOffice(o OfficeConverter)
SetOffice wires the office engine (Options.Office) after the registry is built - the document server's service exists later in the server's boot. Call it before the server starts serving.
func (*Registry) SetOrigins ¶
SetOrigins records how an absolute link's origin is resolved when NO request is in scope — a plugin job runs on the queue, long after the browser left. The tenant then comes from the data (the share's storage), never from a guess: internal/tenanturl.Resolver.ForStorage is what is wired here. Without it a customer's signature request would carry the OPERATOR's hostname.
func (*Registry) SetOutputSink ¶
func (r *Registry) SetOutputSink(s OutputSink)
SetOutputSink wires the committer that lands job outputs on a storage.
func (*Registry) SetPublicURL ¶
SetPublicURL records the base the visitor link is built on. It is the fallback; SetOrigins is what a multi-tenant install answers with.
func (*Registry) SetStorageResolver ¶
SetStorageResolver wires (or replaces) the driver resolver jobs read through; the server builds it after the registry.
func (*Registry) SetUIOrigin ¶ added in v0.48.0
SetUIOrigin sets the separate origin interfaces are served from (FILEX_APP_UI_ORIGIN, with its base path, no trailing slash); "" for filex's own.
func (*Registry) SetUpgradeListener ¶ added in v0.48.0
func (r *Registry) SetUpgradeListener(f UpgradeListener)
SetUpgradeListener wires the listener (the realtime hub).
func (*Registry) SetUserScope ¶
SetUserScope wires the function that puts the acting user's tenant scope on a job context, so users_lookup from a queued job sees the same directory the user's own requests see. Nil = single-tenant, unscoped.
func (*Registry) SetVisibility ¶
func (r *Registry) SetVisibility(fn func(ctx context.Context, u *model.User, storageID int64, rel string) bool)
SetVisibility wires the check state_list runs on every row: a plugin may keep state on a file the person asking has no right to see, and a listing is not a way around the ACL. Nil = everything passes.
func (*Registry) StartScheduler ¶
StartScheduler runs the schedule until ctx ends. Call it once at boot, after the job queue is wired.
It does not poll on a fixed beat: after each pass it sleeps until the next row is actually due, capped at schedulePollCeiling so a row another process wrote is picked up too. That is what makes "to the minute" true — an item due at 03:00:00 runs at 03:00:00, not at the next tick of a one-minute timer.
func (*Registry) StartSweeper ¶
StartSweeper runs SweepPages every hour until ctx ends.
func (*Registry) StartUpdater ¶ added in v0.47.0
StartUpdater runs the daily check until ctx ends. enabled is the operator's switch (FILEX_APP_PLUGIN_UPDATE_CHECK); a demo never runs it. The time of the last check is stored, so a restart neither skips a day nor checks at every boot.
func (*Registry) StatusOf ¶
StatusOf builds the list row. ⚠ Nil-safe receiver: the wire-fixture test calls it on a nil registry, which then reports languages without coverage.
func (*Registry) StorageName ¶
StorageName is a storage's name, or "" when it is gone (or unreadable) — what the panel prints beside a lock instead of the storage's id.
func (*Registry) SweepPages ¶
SweepPages removes the exposed copies of links that are gone. Called hourly by the server; safe to call any time.
⚠ It walks the DIRECTORIES rather than querying for dead rows, because a directory can outlive its row: DeleteShare (the administrator's hard delete) leaves nothing to join against, and those copies would then sit on disk until somebody noticed. A directory is removed when its share is gone, or when the share has been dead for longer than the grace period.
func (*Registry) SweepSchedule ¶
SweepSchedule drops finished rows whose due time is past the retention window. Called once an hour from the schedule loop.
It measures on due_at rather than updated_at on purpose: due_at is always written from Go and updated_at from the engine's CURRENT_TIMESTAMP, and comparing a Go time against an engine-formatted column is how a sweep silently stops matching anything.
func (*Registry) ThumbLimits ¶ added in v0.50.0
ThumbLimits answers an app's thumbnail limits.
func (*Registry) ThumbnailHandlers ¶ added in v0.50.0
func (r *Registry) ThumbnailHandlers() []assoc.AppHandler
ThumbnailHandlers lists the running apps that draw thumbnails, by name - the thumbnail half of assoc.Source.
func (*Registry) Tick ¶
func (r *Registry) Tick(ctx context.Context, p *Installed, now, windowEnd time.Time) (*wire.TickOutput, error)
Tick wakes one plugin and returns what it wants done. Exported so a test (and a future "run it now" button) can drive one wake-up on its own.
The call gets a READ-ONLY scope with no storage and no actor: the same shape a screen gets. It may read settings and its own state, look people up, notify, mail and make granted HTTP calls; it may not write files, write state, take locks or sign. Those belong in the actions it schedules, which run as real jobs with a real scope.
func (*Registry) UICall ¶ added in v0.48.0
func (r *Registry) UICall(ctx context.Context, plugin, view string, storageID int64, rels []string, actor *model.User, locale, method string, params json.RawMessage) (json.RawMessage, error)
UICall runs `ui_call` for view (an interface view of plugin) with method and params, on the files the interface was opened with.
func (*Registry) UIHandler ¶ added in v0.48.0
UIHandler answers the interface route. `origin` says, per request, the origin (with the base path, no trailing slash) the browser reached this route at — `<P>` is built from it — and whether the request may be served here at all (false: 404, e.g. a separate interface origin is configured and this is not it).
func (*Registry) UILocale ¶
UILocale is one language's strings, merged over every running app that ships it; nil when none does.
⚠ First app (by name) wins a contested key — arbitrary, but stable across restarts, which is what matters to somebody reading the screen. ⚠ An empty value is left out rather than served: an app that has not translated a string yet must fall back to English, not blank it.
func (*Registry) UILocaleCodes ¶
UILocaleCodes lists the languages the running apps add, sorted — the tags the server's catalogue may answer in besides English and Turkish.
func (*Registry) UILocaleList ¶
func (r *Registry) UILocaleList() []UILocaleInfo
UILocaleList is every language the running apps add, by tag.
func (*Registry) UIString ¶
UIString is ONE key of one language, under the same rules as UILocale (running apps only, first app by name wins, an empty value is no value) — without building the whole ~3 000-key map. It is how the server's own catalogue (internal/srvtext) reads a pack: a mail or a public page asks for a few dozen keys, and UILocale would merge every string of every pack for each of them.
func (*Registry) Unlock ¶
Unlock lifts a lock by force — the administrator's override for a plugin that will never come back to lift it. Returns false when nothing was locked there.
func (*Registry) Upgrade ¶
func (r *Registry) Upgrade(ctx context.Context, id int64, in *InstallInput) (*Status, *DryRunAnswer, error)
Upgrade replaces the module + manifest of an installed plugin. A manifest that asks for a permission not yet granted answers permissions_changed until the request grants it; a narrower manifest simply narrows the grant.
func (*Registry) UserPermissions ¶ added in v0.49.0
func (r *Registry) UserPermissions() []UserPermRow
UserPermissions lists every installed app's user permissions (manifest `user_permissions`), app by app in install order — what the role editor and a person's exceptions offer under the app's name. A stopped app's are listed too: the decision outlives a restart.
func (*Registry) VerifyUnlock ¶
VerifyUnlock reports whether an unlock cookie belongs to this link.
func (*Registry) ViewEvent ¶
func (r *Registry) ViewEvent(ctx context.Context, plugin, view string, storageID int64, rels []string, actor *model.User, locale string, in wire.ViewEventInput) (*wire.Surface, error)
ViewEvent runs one view event and returns the sanitised surface.
func (*Registry) WakeSoon ¶
WakeSoon brings an app's hourly wake-up forward to a few seconds from now.
It is how the host tells an app that something it cannot see happened to one of its own things — today, a PERSON ended one of its links from the Shares screen (handlers: appLinkEnded). ⚠⚠ It carries no event and no payload, on purpose: the app is not told WHAT happened, it is woken, and its `tick` asks the host about its own links (`share_state` → the link's facts) exactly as it does every hour. One mechanism — the wake-up — and one way of learning — asking — rather than a revoke callback living beside them with its own delivery, retry and ordering rules. Without the nudge the same wake-up still notices within the hour; the nudge only makes it prompt.
A no-op for an app without the `schedule` grant, a stopped app and a demo instance — each of those is simply not woken, which is what they already were.
type Runtime ¶
type Runtime struct {
// contains filtered or unexported fields
}
Runtime owns the compilation cache and the per-host settings.
func NewRuntime ¶
New prepares a runtime. cacheDir holds compiled modules; "" disables the on-disk cache (tests).
func (*Runtime) Compile ¶
func (r *Runtime) Compile(ctx context.Context, wasmPath, sha256Hex string, m *Manifest, fns []HostFunc, logger func(level, msg string)) (*Compiled, error)
Compile validates the module against sha256 (lower-hex; "" skips the check) and compiles it with the given host functions.
type Scope ¶
type Scope struct {
// contains filtered or unexported fields
}
Scope is one call's ticket. Build with newScope; close with Close.
func (*Scope) Close ¶
func (s *Scope) Close()
Close shuts every open handle and removes the spool.
⚠ It also abandons any share this call PROMISED and did not keep (a job that failed, an output the plugin never named). Nothing has to be undone in the database — a promise is the absence of a row — but the copies staged for it are removed here, on every exit path, rather than left for the sweeper.
type SettingError ¶ added in v0.54.0
type SettingError struct {
FieldProblem
}
SettingError is PutSettings' refusal of one value: the field, why, and the bound it broke. The admin handler answers it 400 with the problem said in the administrator's language.
func (*SettingError) Error ¶ added in v0.54.0
func (e *SettingError) Error() string
type Status ¶
type Status struct {
ID int64 `json:"id"`
Name string `json:"name"`
Version string `json:"version"`
Label wire.Text `json:"label"`
Description wire.Text `json:"description,omitempty"`
Icon string `json:"icon,omitempty"`
Homepage string `json:"homepage,omitempty"`
Enabled bool `json:"enabled"`
State string `json:"state"`
StateError string `json:"state_error,omitempty"`
Source string `json:"source"`
SourceURL string `json:"source_url,omitempty"`
// ManifestURL: where a URL install reads its manifest (the update check's
// address; SourceURL is the module's for an app with one).
ManifestURL string `json:"manifest_url,omitempty"`
SHA256 string `json:"sha256"`
Signed bool `json:"signed"`
Permissions []string `json:"permissions"`
// Scheduled says this app is woken once an hour and runs work of its
// own choosing — the one thing on this row that happens with nobody
// present, so the list can mark it.
Scheduled bool `json:"scheduled"`
Actions int `json:"actions"`
Views int `json:"views"`
PublicPages int `json:"public_pages"`
// Kind is KindApp or KindLanguagePack (langpack.go). A language pack has
// no module, so `sha256` is the hash of its MANIFEST — the thing that was
// verified and, on an instance that requires signatures, signed.
Kind string `json:"kind"`
// Languages are the languages this app adds to filex itself, each with
// how much of the CURRENT catalogue it covers. Absent when it adds none.
Languages []LanguageRow `json:"languages,omitempty"`
// Compat is the manifest's `filex` range against the running filex
// (compat.go); absent when it names none. `ok: false` on an installed app
// is a warning, not a stop: it keeps running (Load says why).
Compat *Compat `json:"compat,omitempty"`
// UpdateSource is where newer versions are looked for: github | url, or
// absent when there is nowhere to ask (an uploaded app).
UpdateSource string `json:"update_source,omitempty"`
// Update is what the last check found; absent before the first one.
Update *UpdateInfo `json:"update,omitempty"`
// UpdateSaid is the line the Apps list shows about the app's updates,
// in the reader's language (handlers sayStatus, 0.55): a newer version
// that needs another filex, what an approval adds, an automatic update
// undone, a source that could not be read, or no source to check. Empty
// where a status word says it all (up to date, available).
UpdateSaid string `json:"update_said,omitempty"`
// Engine: the app runs a WebAssembly module. False for a language pack
// and for an app that is only an interface.
Engine bool `json:"engine"`
// UI describes the app's own interface; absent when it has none.
UI *UIInfo `json:"ui,omitempty"`
// Previous is the version an upgrade replaced, kept to go back to
// (versions.go); absent when none is kept.
Previous *PreviousVersion `json:"previous,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Status is one plugin as the admin list shows it.
type ThumbLimits ¶ added in v0.50.0
type ThumbLimits struct {
// MaxInputMB is the largest file the app is sent (MiB).
MaxInputMB int `json:"max_input_mb"`
// TimeoutS is the time it has per file.
TimeoutS int `json:"timeout_s"`
// MemoryMB is its memory in a thumbnail call (MiB).
MemoryMB int `json:"memory_mb"`
// Concurrency is how many files it draws at once.
Concurrency int `json:"concurrency"`
}
ThumbLimits are an app's thumbnail limits as the administrator sees them.
type ThumbLimitsAnswer ¶ added in v0.50.0
type ThumbLimitsAnswer struct {
Values ThumbLimits `json:"values"`
Stored ThumbLimits `json:"stored"`
Defaults ThumbLimits `json:"defaults"`
Min ThumbLimits `json:"min"`
Max ThumbLimits `json:"max"`
Ext []string `json:"ext"`
Mime []string `json:"mime"`
}
ThumbLimitsAnswer is the answer of GET/PUT …/thumbnails: what is in force, what the administrator stored (0 = the default), the defaults and the bounds, and the kinds the app draws.
type UIExternalRow ¶ added in v0.48.0
type UIExternalRow struct {
URL string `json:"url"`
As string `json:"as"`
// Mode is "mirror" (filex serves its own checked copy; no browser asks
// the address) or "live" (the reader's browser fetches it).
Mode string `json:"mode"`
SHA256 string `json:"sha256,omitempty"`
Bytes int64 `json:"bytes,omitempty"`
Reason wire.Text `json:"reason,omitempty"`
// Path is where a mirrored file is served inside the package.
Path string `json:"path,omitempty"`
}
UIExternalRow is one external address as the review shows it.
type UIFileDiff ¶ added in v0.48.0
type UIFileDiff struct {
Added []string `json:"added,omitempty"`
Removed []string `json:"removed,omitempty"`
Changed []string `json:"changed,omitempty"`
AddedCount int `json:"added_count"`
RemovedCount int `json:"removed_count"`
ChangedCount int `json:"changed_count"`
}
UIFileDiff is how an upgrade's interface files differ, by name. Each list is cut at maxUIFileDiff names; the counts are whole.
type UIInfo ¶ added in v0.48.0
type UIInfo struct {
SHA256 string `json:"sha256"`
// Files and Bytes are the bundle's file count and zipped size.
Files int `json:"files"`
Bytes int64 `json:"bytes"`
// Unpacked is what the files come to.
Unpacked int64 `json:"unpacked"`
// CSP are the script-policy exceptions it asks for.
CSP []string `json:"csp,omitempty"`
// External are the addresses outside the package, each mirrored or live.
External []UIExternalRow `json:"external,omitempty"`
}
UIInfo is an interface as the admin screens describe it — the install review, the upgrade's comparison, the Apps list.
type UILocaleInfo ¶
type UILocaleInfo struct {
Code string `json:"code"`
// Source is always "plugin" here; the field is the client's
// PublicLocaleOption, which also describes the built-in languages.
Source string `json:"source"`
// Plugin names the app that brought it (the first, by name, when several
// do) — shown beside the language so nobody wonders where it came from.
Plugin string `json:"plugin"`
RTL bool `json:"rtl,omitempty"`
}
UILocaleInfo is one language the running apps add, as GET /api/public/branding lists it. ⚠ No strings: those are fetched for the one language a visitor actually picks (UILocale, GET /api/public/ui-locales/ {code}). A complete language is ~150 KB of JSON, and the branding answer is read by every public page and every panel start.
type UIRef ¶ added in v0.48.0
type UIRef struct {
// URL is the interface file's address: relative to the server's root
// (`/_appui/<app>/<sha16>/<file>`, joined with the client's API base),
// or absolute when interfaces have an origin of their own.
URL string `json:"url"`
// Grants are what the app was granted — what its bridge calls may do.
Grants []string `json:"grants"`
// Engine: the app has a module (engine.call and job.submit answer).
Engine bool `json:"engine"`
// Version is the app's version (the "updated" note compares it).
Version string `json:"version"`
}
UIRef is how a client opens an app's own interface.
type URLInput ¶
type URLInput struct {
URL string `json:"url"`
ManifestURL string `json:"manifest_url"`
SHA256 string `json:"sha256"`
Signature string `json:"signature"`
}
URLInput is the JSON body of a URL install.
type UpdateInfo ¶ added in v0.47.0
type UpdateInfo struct {
CheckedAt *time.Time `json:"checked_at,omitempty"`
Status string `json:"status,omitempty"`
// Version is the newer version found (available, needs_approval,
// failed), or the newest one this filex cannot run (incompatible).
Version string `json:"version,omitempty"`
// Ref is the git ref that version is read from (a GitHub source).
Ref string `json:"ref,omitempty"`
// Requires: incompatible — the range that version declares, or ">" this
// filex when its manifest carries what this filex does not know (a field
// a newer filex added: peekManifest).
Requires string `json:"requires,omitempty"`
// Notes are the source's release notes for Version, as plain text
// (a GitHub release's body, clipped).
Notes string `json:"notes,omitempty"`
// Added / AddsModule: needs_approval — what the administrator is asked
// to approve (DryRunUpgrade).
Added []string `json:"added,omitempty"`
AddsModule bool `json:"adds_module,omitempty"`
// Refusal: failed / check_failed — the same refusal an install answers,
// so the panel says it in the reader's words with the wizard's sentences.
Refusal *InstallRefusal `json:"refusal,omitempty"`
// Auto is the last automatic update filex 0.47 made, kept across checks
// for the record. Nothing sets it any more.
Auto *AutoUpdated `json:"auto,omitempty"`
// Announced is "<status>@<version>" as last told to the administrators,
// so a daily check does not ring the bell again for the same thing.
Announced string `json:"announced,omitempty"`
}
UpdateInfo is what the last check found for one app — stored with it (app_plugins.update_json) and shown on the Apps list.
type UpdateReport ¶ added in v0.47.0
type UpdateReport struct {
CheckedAt time.Time `json:"checked_at"`
Checked int `json:"checked"`
Updated []string `json:"updated"`
Available []string `json:"available"`
NeedsApproval []string `json:"needs_approval"`
Failed []string `json:"failed"`
}
UpdateReport is one check, as "Check now" answers it: how many apps were asked, and the names of those that moved, wait, or failed.
type UpgradeListener ¶ added in v0.48.0
type UpgradeListener func(app, version string)
UpgradeListener hears every approved version change (an upgrade, a roll-back): the explorers that are open tell their interfaces to reload.
type UserPermRow ¶ added in v0.49.0
type UserPermRow struct {
Key string `json:"key"` // app.<app>.<id>
App string `json:"app"`
AppLabel wire.Text `json:"app_label"`
ID string `json:"id"`
Label wire.Text `json:"label"`
Description wire.Text `json:"description,omitempty"`
Default string `json:"default"`
}
UserPermRow is one app user permission as the role editor lists it.
type UserRow ¶
type UserRow struct {
// UserID, not `id`: the row doubles as a people-picker VALUE, whose
// shape the surface contract fixes as {user_id, email, name}.
UserID int64 `json:"user_id"`
Email string `json:"email"`
Name string `json:"name,omitempty"`
}
UserRow is what users_lookup and GET /api/files/plugins/users return: the directory entry a picker needs and nothing else (no role, no flags).
type ViewRow ¶
type ViewRow struct {
Plugin string `json:"plugin"`
ID string `json:"id"`
Placement string `json:"placement"`
Label wire.Text `json:"label"`
Icon string `json:"icon,omitempty"`
Applies wire.Applies `json:"applies"`
// UI: the view is the app's own interface.
UI *UIRef `json:"ui,omitempty"`
// Requires is the app's user permission the view needs
// (app.<app>.<id>), empty for none. The list handler drops what the
// caller does not hold.
Requires string `json:"requires,omitempty"`
RequiresDefault string `json:"-"`
}
ViewRow is one non-modal view (inspector/home) the explorer may offer.
Source Files
¶
- appclock.go
- applies_override.go
- assets.go
- compat.go
- e2eplain.go
- engines.go
- errors.go
- fetch.go
- guard.go
- hostfn.go
- jobs.go
- jobtext.go
- langpack.go
- license_hold.go
- logs.go
- manifest.go
- office.go
- outbound.go
- permissions.go
- permissions_coedit.go
- procattr_unix.go
- public.go
- public_pin.go
- public_promised.go
- refusal_words.go
- registry.go
- runtime.go
- schedule.go
- scope.go
- seal.go
- signing.go
- surface_values.go
- thumbnails.go
- uibundle.go
- uicall.go
- uimanifest.go
- uinewdoc.go
- uipolicy.go
- uiserve.go
- updates.go
- util.go
- versions.go
- views.go