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 CheckOutboundURL(raw string) error
- func CheckRouteOutput(out *wire.RouteOutput) error
- func CompatEnforced() bool
- func DecodeInstallBody(b []byte) (map[string]json.RawMessage, error)
- func DescribeBudget(m *Manifest) time.Duration
- func EncodeJobText(t wire.Text) string
- func EngineLabel(lang, id string) string
- func ExposedFiles(sh *model.Share) []wire.FileRef
- func ExtraKinds() []string
- 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 OutputFolderStorage(params map[string]any) int64
- 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 SetOutputFolderStorage(params map[string]any, storageID int64)
- 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 AppMail
- 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 EngineHost
- type EraseAnswer
- type EraseCounts
- type ExtraCatalogAnswer
- type ExtraCatalogError
- type ExtraCatalogFile
- type ExtraCatalogItem
- type ExtraCatalogRow
- type ExtraFile
- type ExtrasAnswer
- 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) NeedsSetup() bool
- func (m *Manifest) Route(id string) (wire.Route, 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 OfficeEnginePackage
- type OfficeError
- type OfficePreparer
- 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) AddRouteBase(ctx context.Context, id int64, route, host, prefix string, tenantID int64, ...) (*SetupBaseView, 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) CompleteSetup(ctx context.Context, id int64, by int64) error
- func (r *Registry) ConfirmRemove(ctx context.Context, id int64, confirm string) (*EraseAnswer, error)
- func (r *Registry) DataInfo() (driver string, nodeLocal bool)
- func (r *Registry) DataUsage(ctx context.Context, app string) (int64, int64)
- func (r *Registry) DecorateOps(ctx context.Context, rows []*ops.Op)
- func (r *Registry) DeleteExtra(id int64, rel string) error
- func (r *Registry) DeleteRouteBase(ctx context.Context, id, baseID int64) error
- func (r *Registry) Dir() string
- func (r *Registry) DrawThumbnail(ctx context.Context, app string, req assoc.DrawRequest) ([]byte, error)
- func (r *Registry) EngineHandlers() []assoc.AppHandler
- func (r *Registry) Engines(ctx context.Context) map[string]bool
- func (r *Registry) EraseFacts(ctx context.Context, id int64) (*EraseAnswer, error)
- func (r *Registry) ExtraCatalog(ctx context.Context, id int64, kind string) (*ExtraCatalogAnswer, error)
- func (r *Registry) Extras(id int64) (*ExtrasAnswer, error)
- 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) ForgetLinkLive()
- 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) InstallExtraItem(ctx context.Context, id int64, kind, item string) ([]ExtraFile, 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) OfficeEngines() []OfficeEnginePackage
- 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) PatchRouteBase(ctx context.Context, id, baseID int64, enabled, makeDefault *bool) (*SetupBaseView, error)
- func (r *Registry) PutExtra(id int64, rel string, src io.Reader) (*ExtraFile, error)
- 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) Reconfigure(ctx context.Context, id int64, confirm string, by int64) 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) ReviewUpdate(ctx context.Context, id int64) (*InstallInput, 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) Route(ctx context.Context, app, route string, tenant int64, in wire.RouteInput) (*wire.RouteOutput, error)
- func (r *Registry) RouteBases() []shortlink.Base
- 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) SetEngineHost(h EngineHost)
- 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) SetRouteHosts(h RouteHosts)
- func (r *Registry) SetRoutesChanged(fn func())
- 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) SetupStatus(ctx context.Context, id int64) (*SetupAnswer, error)
- func (r *Registry) SetupView(ctx context.Context, id int64, actor *model.User, locale string, ...) (*wire.Surface, bool, error)
- func (r *Registry) Shorten(ctx context.Context, actor *model.User, locale string, in wire.ShortenInput) (*wire.ShortenOutput, error)
- func (r *Registry) Shortener() (*Installed, bool)
- func (r *Registry) ShortenerConflict(name string, m *Manifest) string
- func (r *Registry) ShortenerRequires() string
- 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) TenantKey(ctx context.Context, providerID int64) 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 RouteBaseError
- type RouteBaseRow
- type RouteHosts
- type Runtime
- type Scope
- type SettingError
- type SetupAnswer
- type SetupAppStep
- type SetupBaseView
- type SetupData
- type SetupPermission
- type SetupRecord
- type SetupRoute
- 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 ( // MaxExtraFileBytes is one added file's ceiling. The largest of the // Document Server's dictionaries is Turkish (14.5 MB zipped, several // times that as the .dic text the spell checker reads). MaxExtraFileBytes int64 = 128 << 20 // MaxExtrasBytes is one app's added files together: every one of the // Document Server's 50 dictionaries (227 MB) and room beside them. MaxExtrasBytes int64 = 1 << 30 )
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 MaxCallTimeout = 60 // MinDescribeTimeout is the least describe gets (seconds), at install, // upgrade and every load (DescribeBudget). MinDescribeTimeout = 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" // ErrCodeShortenerTaken: another app already holds the link-shortener // role (routes.go) - one at a time. ErrCodeShortenerTaken = "shortener_taken" // 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" // ErrCodeLoadFailed: the module did not load - it did not compile, did // not start or crashed in describe - so nothing was installed. Not // describe_mismatch, which is a module that answered as another program. ErrCodeLoadFailed = "load_failed" // ErrCodeLoadTimeout: the module ran out of time while it was being // started and asked to describe itself (DescribeBudget) - a busy // server, worth another try. ErrCodeLoadTimeout = "load_timeout" )
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 ExtraCatalogFormat = "filex-extras/1"
ExtraCatalogFormat is the catalog's `format`.
const ExtraPrefix = "extra/"
ExtraPrefix is the folder of the package's address the added files are served under.
const ( // MaxOfficeEngineBytes is engine.zip's ceiling, zipped: x2t-server.wasm is // about 40 MB, the rest a few. MaxOfficeEngineBytes = 256 << 20 )
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 StateSetup = "setup"
StateSetup is an app waiting to be set up. It overlays "running" only, like StateUnlicensed.
const UIPrefix = "/_appui/"
UIPrefix is the route's first segment.
Variables ¶
var ( // ErrExtraPath: the path is not one of a kind filex takes (extraKinds). ErrExtraPath = errors.New("extras: not a path an added file may have") // ErrExtrasUnused: the app's interface cannot read added files (no // `ui:package-fetch`). ErrExtrasUnused = errors.New("extras: this app's interface reads no added files") // ErrExtraTooLarge: one file over MaxExtraFileBytes. ErrExtraTooLarge = errors.New("extras: the file is larger than one added file may be") // ErrExtrasFull: the app's added files would pass MaxExtrasBytes or // maxExtraFiles. ErrExtrasFull = errors.New("extras: the app's added files are at their ceiling") // ErrExtraNotText: a text kind whose bytes are not text (a zip, a // binary picked by mistake). ErrExtraNotText = errors.New("extras: the file is not text") // ErrExtraMissing: no such added file. ErrExtraMissing = errors.New("extras: no such added file") )
Why an added file was refused or not found. The handler says each in the reader's words (server.error.extra_*).
var ( // ErrExtraUndeclared: the app does not name the kind in `ui.extras`. ErrExtraUndeclared = errors.New("extras: this app does not take files of that kind") // ErrExtraNoCatalog: the app names the kind but offers no catalog for it. ErrExtraNoCatalog = errors.New("extras: this app's release offers no catalog of that kind") // ErrExtraNoCatalogSource: the catalog's address needs a tag or a // manifest address this install does not have (an upload). ErrExtraNoCatalogSource = errors.New("extras: the catalog is read where the app was installed from, and this install has no such address") // ErrExtraItemMissing: the catalog has no such item. ErrExtraItemMissing = errors.New("extras: the catalog has no such item") )
Why a catalog could not be offered or installed (handlers say each in the reader's words, server.error.extras_*).
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 ( ErrSetupAppStep = errors.New("setup_app_step") ErrSetupNoBase = errors.New("setup_no_base") ErrSetupDone = errors.New("setup_done") ErrNoSuchRoute = errors.New("no_such_route") ErrNoSuchBase = errors.New("no_such_base") ErrRouteBaseTaken = errors.New("route_base_taken") ErrRouteHostTaken = errors.New("route_host_taken") ErrRouteHostFilex = errors.New("route_host_is_filex") ErrConfirm = errors.New("confirm_mismatch") ErrNoSetup = errors.New("setup_not_needed") ErrNoSuchTenant = errors.New("no_such_tenant") )
Errors the setup doors answer with their codes.
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 ErrNoRoute = errors.New("wasmplugin: the route is not answered now")
ErrNoRoute: the app is not answering that route now (not set up, stopped, removed, held by its license).
var ErrOfficePreparing = errors.New("office engine: being prepared")
ErrOfficePreparing: the engine an app brings is still being compiled, and nothing else takes the job meanwhile.
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 back end is configured")
ErrOfficeUnconfigured: nothing converts office documents here (no app brings an engine, 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 CheckOutboundURL ¶ added in v0.60.0
CheckOutboundURL is the rule for an address filex sends a visitor to on an app's word: absolute http or https, a host, no user name or password, at most 2048 bytes.
func CheckRouteOutput ¶ added in v0.60.0
func CheckRouteOutput(out *wire.RouteOutput) error
CheckRouteOutput holds a route's answer to the contract: exactly one of a redirect, a page and a miss; a redirect (and a page's link) an absolute http(s) address, no user name or password, at most 2048 bytes; a page's texts short.
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 DescribeBudget ¶ added in v0.60.0
DescribeBudget is describe's budget: the app's call budget, and never less than MinDescribeTimeout.
⚠⚠ Why (0.57 chain, 2026-10-16): describe is filex's own proof, at install and every load, and nobody waits on it the way a person waits on a screen. With the call budget alone (15 s by default, sign's 30), two installs on an overloaded machine (two race-test jobs starting beside the suite, memory and disk stalled) ran out of it while the module was still starting, and were refused - as describe_mismatch, "the build and the manifest do not belong together", about a module that was fine; the same installs took 6 s and 2 s a minute later. A busy server is not a different program.
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 EngineLabel ¶ added in v0.60.0
EngineLabel is an engine as a label names it: the product's own spelling (enginebin.DisplayName), except the office engine. Since 0.57 that is the Office editor app's engine OR a connected ONLYOFFICE Document Server, so "ONLYOFFICE" beside the other engines (Admin → Apps, the install review's permission line) named one of the two as if it were the only one. It is "Office engine", in the reader's language. Where the words say what to CONNECT (a missing engine's `name` in the review and the menu), the product name stays.
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 ExtraKinds ¶ added in v0.60.0
func ExtraKinds() []string
ExtraKinds are the kinds' names, for the administrator's screen.
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 OutputFolderStorage ¶ added in v0.60.0
OutputFolderStorage reads back the storage a chosen folder is pinned to, 0 when there is none (no folder, or a row queued before 0.59).
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 SetOutputFolderStorage ¶ added in v0.60.0
SetOutputFolderStorage pins the override's chosen folder (mode "folder") to storage storageID. Call it after SetOutputOverride; without an override it does nothing.
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 AppMail ¶ added in v0.60.0
type AppMail struct {
To, Subject, Body string
// App is the app's label in Lang.
App string
// Lang is the mail's language: the one the app states (MailSendIn), else
// the language the call runs in, else the instance default.
Lang string
}
AppMail is one mail an app sends: what it wrote, and the app's name in the mail's language (filex's own sentence under it, "Sent by the {app} app on filex", is the template's).
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"`
// FromManifest: the review was read from the manifest alone (a source's
// review: fetch.go, "A REVIEW READS THE MANIFEST"). The module, the
// interface and the office engine are named by the sha256 the manifest
// pins; their sizes, the interface's file count and an upgrade's file
// list are not known yet. The approval downloads them and holds every
// byte to those pins.
FromManifest bool `json:"from_manifest,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 EngineHost ¶ added in v0.60.0
type EngineHost interface {
// EnginesChanged: install, upgrade, removal, a switch, a license hold.
// The host reads OfficeEngines again.
EnginesChanged()
// ReleaseEngine ends every process that holds app's engine files open
// (on Windows a file a process holds cannot be moved).
ReleaseEngine(app string)
}
EngineHost is the server side of the apps' engines: told when the set of running engines may have changed, and asked to let go of an app's files before they are moved or removed.
type EraseAnswer ¶ added in v0.60.0
type EraseAnswer struct {
Counts EraseCounts `json:"counts"`
Warning wire.Text `json:"warning,omitempty"`
Confirm string `json:"confirm"`
}
EraseAnswer is GET …/{id}/erase.
type EraseCounts ¶ added in v0.60.0
type EraseCounts struct {
DataKeys int64 `json:"data_keys"`
DataBytes int64 `json:"data_bytes"`
StateRows int64 `json:"state_rows"`
Locks int64 `json:"locks"`
Links int64 `json:"links"`
}
EraseCounts is what Reconfigure (and removing the app) erases.
func (EraseCounts) Any ¶ added in v0.60.0
func (c EraseCounts) Any() bool
Any reports whether there is anything to erase.
type ExtraCatalogAnswer ¶ added in v0.60.0
type ExtraCatalogAnswer struct {
Kind string `json:"kind"`
Items []ExtraCatalogRow `json:"items"`
}
ExtraCatalogAnswer is a kind's catalog for one app (GET …/extras-catalog/{kind}).
type ExtraCatalogError ¶ added in v0.60.0
type ExtraCatalogError struct {
// File is the item's file it is about ("" for the catalog itself).
File string
Msg string
}
ExtraCatalogError is a catalog, or one of its files, that could not be read or is not what the manifest or the catalog pins.
func (*ExtraCatalogError) Error ¶ added in v0.60.0
func (e *ExtraCatalogError) Error() string
type ExtraCatalogFile ¶ added in v0.60.0
type ExtraCatalogFile struct {
// Path is where it goes under the kind's folder (`pl_PL/pl_PL.dic.txt`).
Path string `json:"path"`
URL string `json:"url"`
Size int64 `json:"size"`
SHA256 string `json:"sha256"`
}
ExtraCatalogFile is one file of a catalog item.
type ExtraCatalogItem ¶ added in v0.60.0
type ExtraCatalogItem struct {
ID string `json:"id"`
Label string `json:"label,omitempty"`
License string `json:"license,omitempty"`
Files []ExtraCatalogFile `json:"files"`
}
ExtraCatalogItem is one thing a catalog offers: a dictionary's language.
type ExtraCatalogRow ¶ added in v0.60.0
type ExtraCatalogRow struct {
ID string `json:"id"`
Label string `json:"label,omitempty"`
License string `json:"license,omitempty"`
// Size is its files' together, as the catalog says them.
Size int64 `json:"size"`
Files int `json:"files"`
// Installed: every file of it is among the app's added files, at the
// catalog's size; Partial: some are.
Installed bool `json:"installed"`
Partial bool `json:"partial,omitempty"`
}
ExtraCatalogRow is one item as the administrator's screen lists it.
type ExtraFile ¶ added in v0.60.0
type ExtraFile struct {
// Path is where it is under extra/ (`dictionaries/pl_PL/pl_PL.dic.txt`).
Path string `json:"path"`
Kind string `json:"kind"`
Size int64 `json:"size"`
Modified time.Time `json:"modified"`
// SHA256 is said by the write that stored it (and its audit row), not
// by the list: hashing every dictionary at every look would be slow.
SHA256 string `json:"sha256,omitempty"`
}
ExtraFile is one file an administrator added to an app.
type ExtrasAnswer ¶ added in v0.60.0
type ExtrasAnswer struct {
Files []ExtraFile `json:"files"`
Bytes int64 `json:"bytes"`
MaxFileBytes int64 `json:"max_file_bytes"`
MaxBytes int64 `json:"max_bytes"`
// Kinds are the kinds the app names in its manifest (`ui.extras`,
// extras_catalog.go): the only ones it is given. Catalogs are those its
// release offers a catalog of (one-click install).
Kinds []string `json:"kinds"`
Catalogs []string `json:"catalogs"`
// Read: the app was granted `ui:package-fetch` and names a kind, so its
// interface can read what is added here. False: nothing would, and a new
// file is refused (ErrExtrasUnused).
Read bool `json:"read"`
}
ExtrasAnswer is an app's added files, its ceilings and whether its interface reads them at all.
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:"-"`
// Review reads the manifest alone, for a review (a dry run): see
// InstallInput.ReviewOnly. Never the API's: the handler sets it for a
// dry run.
Review bool `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
// Engine is the office engine (engine.zip) when the manifest has an
// `engines.office` block; consumed, held to the manifest's sha256.
Engine 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
// ReviewOnly: nothing but the manifest was downloaded (GitHubInput.Review,
// URLInput.Review, ReviewUpdate) - its pins stand for the module, the
// interface bundle and the office engine. Only a dry run takes it; an
// install or an upgrade refuses it (fetch.go, "A REVIEW READS THE
// MANIFEST"). ReviewModule: the install would download a module, pinned
// by SHA256.
ReviewOnly bool
ReviewModule bool
// 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 counts current catalogue keys applicable to this language, excluding
// plural forms its CLDR rules never select; 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) NeedsSetup ¶ added in v0.60.0
NeedsSetup reports whether the app is set up by an administrator before it runs: it says so (`setup`), or it has routes, which have no address until it is given 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 back end converts 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 server's chooser between the app's engine and the connected document server (a fake in tests).
type OfficeEnginePackage ¶ added in v0.60.0
type OfficeEnginePackage struct {
App, Version string
Label wire.Text
// Engine is engine.zip; UI the interface bundle, whose EditorDir holds
// the editor's scripts and fonts.
Engine, EngineSHA256 string
UI, UISHA256 string
EditorDir string
}
OfficeEnginePackage is an installed app's office engine, as the server's engine runner needs it: both zips, each with the hash it was installed with.
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 OfficePreparer ¶ added in v0.60.0
OfficePreparer is an OfficeConverter that can say its engine is being prepared (the server's chooser does): Ready is false, and the answer says "being prepared" rather than "not configured".
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
// Data is where apps keep their own data (internal/appdata, the `data`
// permission). Nil answers every data_* call `unavailable`.
Data appdata.Store
// MultiTenant mirrors FILEX_MULTI_TENANT: the `tenant` scope of an app's
// data is the call's tenant. Off, every call is in the platform's scope.
MultiTenant bool
// RoutePool is how many warm instances answer one app's route and
// shortener calls at once (FILEX_APP_ROUTE_POOL; 0 = half the CPUs,
// 1 to 16). See pool.go.
RoutePool int
}
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" // PermData is the app's own key-value store (filex 0.60.0, data.go): // kept beside filex, never in its tables, erased with the app. PermData Permission = "data" // PermPublicRoutes lets the app answer visitors with no account at the // addresses the administrator gives its `routes` (filex 0.60.0). PermPublicRoutes Permission = "public_routes" // PermLinkShortener is the link-shortener role (filex 0.60.0): filex // hands the app each of its links a person asks to shorten, and the app // may ask whether such a link is still open (link_live). PermLinkShortener Permission = "link_shortener" // 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`.
const PermOfficeEngine Permission = "office-engine"
PermOfficeEngine: the app brings an office engine filex runs on the server. Derived from `engines.office`, 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) AddRouteBase ¶ added in v0.60.0
func (r *Registry) AddRouteBase(ctx context.Context, id int64, route, host, prefix string, tenantID int64, makeDefault bool) (*SetupBaseView, error)
AddRouteBase gives one of the app's routes a base. Refusals are *RouteBaseError (the field, the code).
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) CompleteSetup ¶ added in v0.60.0
CompleteSetup finishes the wizard: the app's own step said done, every route has a base it is served on. The app runs from now.
func (*Registry) ConfirmRemove ¶ added in v0.60.0
func (r *Registry) ConfirmRemove(ctx context.Context, id int64, confirm string) (*EraseAnswer, error)
ConfirmRemove is what removing an app asks: when it keeps anything, the app's name typed back. ErrConfirm with the counts when it is missing or wrong.
func (*Registry) DataInfo ¶ added in v0.60.0
DataInfo says where apps' data lives, for the setup wizard and the review.
func (*Registry) DataUsage ¶ added in v0.60.0
DataUsage is how many keys and bytes an app keeps (Reconfigure's and removal's count).
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) DeleteExtra ¶ added in v0.60.0
DeleteExtra removes one added file of app id, and the folders it leaves empty.
func (*Registry) DeleteRouteBase ¶ added in v0.60.0
DeleteRouteBase removes a base while the setup is not finished; after that a base is only switched off.
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) EngineHandlers ¶ added in v0.60.0
func (r *Registry) EngineHandlers() []assoc.AppHandler
EngineHandlers are the office engines as Default apps lists them (the `engine` capability, internal/assoc): one handler per app that brings one.
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) EraseFacts ¶ added in v0.60.0
EraseFacts counts what the app keeps.
func (*Registry) ExtraCatalog ¶ added in v0.60.0
func (r *Registry) ExtraCatalog(ctx context.Context, id int64, kind string) (*ExtraCatalogAnswer, error)
ExtraCatalog answers app id's catalog of kind, each item with whether its files are already among the app's added files.
func (*Registry) Extras ¶ added in v0.60.0
func (r *Registry) Extras(id int64) (*ExtrasAnswer, error)
Extras answers an app's added files (GET …/extras).
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 upgrade ("Review update" → approve on the Apps list). The same search the check makes, so what is approved is what was announced; the decision is the administrator's.
func (*Registry) ForgetLinkLive ¶ added in v0.60.0
func (r *Registry) ForgetLinkLive()
forgetLinkLive drops the kept answers (a link was revoked from filex's own doors: the next visit asks again).
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) InstallExtraItem ¶ added in v0.60.0
func (r *Registry) InstallExtraItem(ctx context.Context, id int64, kind, item string) ([]ExtraFile, error)
InstallExtraItem downloads every file of item from app id's catalog of kind, holds each to the catalog's size and sha256, and only then stores them (PutExtra): a file that does not match leaves nothing new behind.
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) OfficeEngines ¶ added in v0.60.0
func (r *Registry) OfficeEngines() []OfficeEnginePackage
OfficeEngines is every app that brings an office engine and runs now (installed, switched on, loaded, not held by its license), by name.
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) PatchRouteBase ¶ added in v0.60.0
func (r *Registry) PatchRouteBase(ctx context.Context, id, baseID int64, enabled, makeDefault *bool) (*SetupBaseView, error)
PatchRouteBase switches a base on or off, or makes it the route's default. A base is never edited otherwise: a printed address must keep meaning what it meant.
func (*Registry) PutExtra ¶ added in v0.60.0
PutExtra adds (or replaces) one file of app id at rel, a path under extra/, from src. The file is written beside its place and renamed into it once whole, so a reader never sees half of it and a refused write leaves the old file as it was.
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) Reconfigure ¶ added in v0.60.0
Reconfigure erases what the app keeps and puts it back into its setup. confirm must be the app's name. The routes' bases are kept for the wizard to start from, unfinished (they can be removed or added again).
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) ReviewUpdate ¶ added in v0.60.0
ReviewUpdate is FetchUpdate for the review ("Review update"): the same search, and of the version it finds the manifest alone - nothing that takes longer than reading filex-app.json (fetch.go, "A REVIEW READS THE MANIFEST"). The answer is a dry run's input 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) Route ¶ added in v0.60.0
func (r *Registry) Route(ctx context.Context, app, route string, tenant int64, in wire.RouteInput) (*wire.RouteOutput, error)
Route hands one visit to the app that answers the base. tenant is the visited address's tenant (the `tenant` scope of the app's data on this call).
func (*Registry) RouteBases ¶ added in v0.60.0
RouteBases are the bases filex serves now: every enabled base of every route of every app that is set up and running.
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) SetEngineHost ¶ added in v0.60.0
func (r *Registry) SetEngineHost(h EngineHost)
SetEngineHost wires the engine host and tells it what runs now.
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) SetRouteHosts ¶ added in v0.60.0
func (r *Registry) SetRouteHosts(h RouteHosts)
SetRouteHosts wires the router's answers (routes.go in package api).
func (*Registry) SetRoutesChanged ¶ added in v0.60.0
func (r *Registry) SetRoutesChanged(fn func())
SetRoutesChanged hands the router fn, called (on a goroutine of its own) soon after the served bases change - a setup finished, a base added or switched off, an app started, stopped, removed or upgraded - and every routesRefresh anyway, so a change no door announced is picked up too. fn rebuilds the router's snapshot from RouteBases.
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) SetupStatus ¶ added in v0.60.0
SetupStatus answers the wizard's facts for app id.
func (*Registry) SetupView ¶ added in v0.60.0
func (r *Registry) SetupView(ctx context.Context, id int64, actor *model.User, locale string, in wire.ViewEventInput) (*wire.Surface, bool, error)
SetupView answers one event of the app's setup view, for an administrator. The app may keep what it was told in its own data (`data`); a surface that says `done` finishes the app's step.
func (*Registry) Shorten ¶ added in v0.60.0
func (r *Registry) Shorten(ctx context.Context, actor *model.User, locale string, in wire.ShortenInput) (*wire.ShortenOutput, error)
Shorten asks the shortener app for a short address of one of filex's links, for actor. The answer must lie on one of the bases the app was handed.
func (*Registry) Shortener ¶ added in v0.60.0
Shortener is the app holding the link-shortener role now, "" for none: set up, running, with a `link_shortener` block and the grant. One app holds it at a time (the first by name; enabling a second is refused, ShortenerConflict).
func (*Registry) ShortenerConflict ¶ added in v0.60.0
ShortenerConflict names the app that already holds the shortener role when m would be a second one, "" when there is none.
func (*Registry) ShortenerRequires ¶ added in v0.60.0
ShortenerRequires is the user permission key "Get short link" needs ("" for none) - app.<app>.<id>.
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) TenantKey ¶ added in v0.60.0
TenantKey is tenantKey for the callers outside the package (the route door resolves a host's tenant with it).
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 RouteBaseError ¶ added in v0.60.0
RouteBaseError is a base refused, with the field it is about.
func (*RouteBaseError) Error ¶ added in v0.60.0
func (e *RouteBaseError) Error() string
func (*RouteBaseError) Unwrap ¶ added in v0.60.0
func (e *RouteBaseError) Unwrap() error
type RouteBaseRow ¶ added in v0.60.0
type RouteBaseRow struct {
ID int64 `json:"id"`
Host string `json:"host"`
Prefix string `json:"prefix"`
TenantID int64 `json:"tenant_id"`
Enabled bool `json:"enabled"`
Default bool `json:"default"`
}
RouteBaseRow is one base of a route.
type RouteHosts ¶ added in v0.60.0
type RouteHosts struct {
IsFilexHost func(ctx context.Context, host string) bool
Reserved func(first string) bool
OwnOrigin func(ctx context.Context, tenantID int64) string
TenantExists func(ctx context.Context, id int64) bool
}
RouteHosts answers whether a host is one filex itself answers on (its own address, a tenant's, the apps' interface origin, the S3 host...), so it can be no route's host of its own; and whether a path's first segment is one of filex's routes, so it can be no prefix on filex's own address. Set by the router (SetRouteHosts).
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 SetupAnswer ¶ added in v0.60.0
type SetupAnswer struct {
State string `json:"state"`
Needed bool `json:"needed"`
Done bool `json:"done"`
AppStep *SetupAppStep `json:"app_step"`
Routes []SetupRoute `json:"routes"`
Permissions []SetupPermission `json:"permissions"`
Data SetupData `json:"data"`
Warning wire.Text `json:"warning,omitempty"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
// OwnHosts is the host filex itself answers on (its public address): a
// base on "this filex's address" lies on it, and a host of the app's
// own is pointed at it in DNS. Empty when filex has no address.
OwnHosts []string `json:"own_hosts"`
}
SetupAnswer is GET …/{id}/setup.
type SetupAppStep ¶ added in v0.60.0
SetupAppStep is the app's own step.
type SetupBaseView ¶ added in v0.60.0
type SetupBaseView struct {
RouteBaseRow
URL string `json:"url"`
}
SetupBaseView is a base as the wizard draws it.
type SetupData ¶ added in v0.60.0
type SetupData struct {
Uses bool `json:"uses"`
Driver string `json:"driver,omitempty"`
NodeLocal bool `json:"node_local"`
}
SetupData says where the app's own data lives.
type SetupPermission ¶ added in v0.60.0
type SetupPermission struct {
ID string `json:"id"`
Key string `json:"key"`
Label wire.Text `json:"label"`
Description wire.Text `json:"description,omitempty"`
Default string `json:"default"`
}
SetupPermission is one of the app's user permissions, for the "who may use it" step.
type SetupRecord ¶ added in v0.60.0
type SetupRecord struct {
// Done: the wizard was finished; the app runs.
Done bool `json:"done"`
// AppDone: the app's own step said done (its setup view answered
// `done: true`).
AppDone bool `json:"app_done"`
// Routes are the bases given to each of the app's routes, by route id.
Routes map[string][]RouteBaseRow `json:"routes,omitempty"`
NextBase int64 `json:"next_base"`
// CompletedAt / CompletedBy: when and by whom the wizard was finished.
CompletedAt *time.Time `json:"completed_at,omitempty"`
CompletedBy int64 `json:"completed_by,omitempty"`
}
SetupRecord is the host's record of an app's setup.
type SetupRoute ¶ added in v0.60.0
type SetupRoute struct {
ID string `json:"id"`
Label wire.Text `json:"label"`
DefaultPrefix string `json:"default_prefix,omitempty"`
Bases []SetupBaseView `json:"bases"`
}
SetupRoute is one route and its bases.
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"`
// EditorLang is the language the administrator fixed for document
// editors (filex 0.57, #214: External services → ONLYOFFICE → Editor
// language, FILEX_ONLYOFFICE_LANG), "" while each person's own language
// decides. Set per request by the list's handler; the interface is told
// it as `session.editor_lang`.
EditorLang string `json:"editor_lang,omitempty"`
}
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"`
// Review reads the manifest alone, for a review (GitHubInput.Review).
Review bool `json:"-"`
}
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
- data.go
- e2eplain.go
- engines.go
- errors.go
- extras.go
- extras_catalog.go
- fetch.go
- guard.go
- hostfn.go
- jobs.go
- jobtext.go
- langpack.go
- license_hold.go
- logs.go
- manifest.go
- office.go
- office_engine_app.go
- outbound.go
- permissions.go
- permissions_coedit.go
- pool.go
- procattr_unix.go
- public.go
- public_pin.go
- public_promised.go
- refusal_words.go
- registry.go
- routes.go
- routes_manifest.go
- runtime.go
- schedule.go
- scope.go
- seal.go
- setup.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