sqlapplet

package
v0.0.22 Latest Latest
Warning

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

Go to latest
Published: Aug 24, 2026 License: MIT Imports: 32 Imported by: 0

Documentation

Overview

Package sqlapplet makes SQL-defined applets first-class boxer apps (ADR-0132): each applet is one committed markdown document — frontmatter as the manifest, prose as the help page, the first `sql` fence as the play buffer — and the host mints one real app.Manifest per document, serving every instance as an attenuated embedded play (`NewLivePlayApp` with the exploration chrome removed).

Contributing packages register applet books via RegisterBook (an embedded fs.FS of .md documents, mirroring the help facility); the shell calls MintManifests once at startup, before launch resolution, so `--launch <appletId>` and the Apps menu see the minted set.

Index

Constants

View Source
const StoreAppId app.AppIdT = "runtime.appletstore"

StoreAppId is the synthetic identity the applet store service registers under; its SubjectAlias namespaces the persisted documents.

Variables

View Source
var DatasetEvents = env.NewCategorialString(env.Spec{
	Name:        "BOXER_SQLAPPLET_DATASET_EVENTS",
	Default:     "on",
	Description: "dataset binder event path (ADR-0188 §SD3): on = subscribe and act; drop = subscribe but discard, reconcile alone binds (fault injection); off = do not subscribe, poll",
	Category:    env.CategoryE("boxer-sqlapplet"),
}, []string{"on", "drop", "off"})

DatasetEvents is a fault-injection knob for the dataset binder's event path (ADR-0188 §SD3). "on" subscribes to adhoc.event.> and acts on the events (the default); "drop" subscribes but discards every event, which is what a slow consumer on NATS core experiences and leaves the reconcile tick alone to keep the binding in step; "off" does not subscribe at all, the pre-events poll. It exists so the headless lane can show the reconcile working against a running host; it is not an operating knob.

View Source
var DatasetReconcile = env.NewDuration(env.Spec{
	Name:        "BOXER_SQLAPPLET_DATASET_RECONCILE",
	Default:     "30s",
	Description: "dataset binder reconcile interval with events subscribed (ADR-0188 §SD3); a Go duration such as 30s or 5s",
	Category:    env.CategoryE("boxer-sqlapplet"),
})

DatasetReconcile overrides the binder's reconcile interval — how often a window with events subscribed re-asks for pending aliases and verifies its bound handles (ADR-0188 §SD3). The default is the value the binder would use anyway; shorten it for the headless lane or under a lossy transport.

View Source
var WindowSize = env.NewString(env.Spec{
	Name:        "BOXER_SQLAPPLET_WINDOW_SIZE",
	Description: "open an applet window at \"WxH\" logical points (scripted screenshots); empty or unparseable keeps the host's archetype default",
	Category:    env.CategoryE("boxer-sqlapplet"),
})

WindowSize opens an applet at a chosen size, for scripted screenshots.

It mirrors play's `BOXER_PLAY_WINDOW_SIZE` and exists for the same reason: the host's archetype fallback is a 900×640 application window, and an applet whose document places panes in three zones (ADR-0132 Update 2026-08-14) opens with all three of them cramped — which a capture would then record as the shape of the applet rather than the shape of the default window. Inert when unset, so an ordinary launch is unaffected.

Functions

func MintManifests

func MintManifests(logger zerolog.Logger) (minted int, errs []error)

MintManifests parses every registered applet book and registers one factory-backed Manifest per applet with the default app registry (ADR-0132 §SD2). The shell calls it exactly once at startup, after init-time book registrations and before launch resolution, so `--launch <appletId>` and the Apps menu see the minted set.

Minting is best-effort per document — an invalid doc yields an error and mints nothing, valid siblings still mint — because the corpus test (§SD6) is the hard gate; at boot, a partially minted set beats no shell.

func NewEmbedded added in v0.0.15

func NewEmbedded(def *AppletDef, cfg EmbedConfig) (inner *play.PlayApp, err error)

NewEmbedded constructs an attenuated PlayApp for def, ready to render: it resolves the endpoint, stamps identity, applies the AutoRun/Live gates and the minimal toolbar, attenuates tabs, binds any ad-hoc datasets, and grants capabilities. It is the shared core that both the standalone applet (appletApp.Mount) and an embedder call, so every applet-definition invariant holds under embedding (ADR-0132 §SD8, ADR-0134 §SD7). Instance-id salting is per-PlayApp automatically (NewPlayApp), so embedded instances do not collide.

func RegisterBook

func RegisterBook(id string, fsys fs.FS, topics []app.TopicT) (err error)

RegisterBook contributes an applet book: an fs.FS of markdown documents in the ADR-0132 §SD1 shape. Packages call it from init (the help-facility pattern); MintManifests later parses every registered book. The id names the book in diagnostics and must be unique.

topics is the book's default ADR-0158 §SD1 classification, applied to every document that does not override it with its own `topics:` frontmatter. It is required and must be registered: a book whose applets cannot be sectioned is refused here rather than producing manifests the launcher silently drops at registration (§SD9).

Types

type AppletDef

type AppletDef struct {
	Slug     string
	BookID   string
	Title    string
	Icon     string
	Tabs     []TabSel // nil = auto (all result panels; accept/reject decides at render)
	Endpoint EndpointE
	SQL      string
	BandsSQL string // optional `sql bands` aux fence (Timeline panel-local SQL)
	// Preamble is the optional `md preamble` aux fence: explanatory markdown
	// the instance renders above the result panes. It is deliberately its own
	// fence rather than the document's leading prose — an author decides what
	// belongs over the numbers and what belongs in the Definition drawer, and
	// existing applets gain nothing they did not ask for. Note that
	// [scanFences] does not nest, so a preamble cannot itself contain a
	// fenced block.
	Preamble string
	// Class is the ADR-0132 §SD5 security class of SQL, computed at parse
	// time. It gates AutoRun at mount: only QuerySecurityRead applets run on
	// open.
	Class analysis.QuerySecurityClassE
	// HasUnboundSlots notes whether the buffer carries `{name:Type}`
	// placeholders its SET prelude does not bind — signals, in ADR-0097
	// terms. Such an applet opens with the Live toggle preset
	// (panel-written signals re-run the buffer, ADR-0132 §SD3); a fully
	// prelude-bound buffer does not (its params re-run via the strip's
	// prelude rewrite and an explicit or auto Run).
	HasUnboundSlots bool
	// Datasets are the stable ad-hoc dataset aliases the buffer references
	// as keelson('<alias>') (ADR-0134 §SD4). An embedder binds each to an
	// ephemeral handle before mount. The corpus gate treats them as
	// valid-by-declaration.
	Datasets []string
	// DatasetsHint is the frontmatter `datasets_hint`: one line telling a
	// reader how to produce the declared datasets, shown in the applet's
	// notice strip while an alias is still unbound. Optional, and only
	// meaningful alongside Datasets.
	//
	// It exists because the alias is the only thing the runtime knows: play
	// can say `pprof_cpu` has nothing behind it, but only the author knows
	// that imzrt's Profiles tab is what puts something there. Without it the
	// empty state names a table the reader has never heard of.
	DatasetsHint string
	// Source is the document's raw markdown — the definition itself, kept so
	// an instance can show a reader what it was minted from (play's
	// "Definition" drawer). Bytes rather than a parsed markdown.Doc: parsing
	// at mint time would hold a segment tree per corpus document for the
	// whole session, where the drawer needs one per opened applet. A def
	// built by hand rather than parsed carries none, and the drawer is
	// simply absent.
	Source []byte
	// Topics classify the applet by subject for the launcher (ADR-0158
	// §SD2). Set from a frontmatter `topics:` list; nil when the document
	// omits it, in which case the *minter* fills the contributing book's
	// default (see RegisterBook) — the grouping the corpus already carries,
	// which pre-0158 minting discarded. The default lands at mint rather
	// than at parse because ParseDocSource is shared with the runtime store
	// and with embedders, neither of which has a book to default from.
	//
	// A frontmatter topic outside the registered vocabulary fails the parse
	// rather than being dropped: a silently ignored topic would mint an
	// applet the launcher cannot section.
	Topics []app.TopicT
	// Keywords are the document's optional frontmatter `keywords:` list,
	// passed through to the manifest as free retrieval text (ADR-0158 §SD4).
	Keywords []string
}

AppletDef is one parsed applet document, ready to mint.

func ParseBook

func ParseBook(bookID string, fsys fs.FS) (defs []*AppletDef, errs []error)

ParseBook parses every markdown document of one applet book into applet definitions. A document without a role-less `sql` fence is a plain prose page and yields no definition (a book may carry an overview page); every violation of the ADR-0132 §SD1/§SD6 rules yields one error naming the document. defs come back sorted by slug.

func ParseDocSource

func ParseDocSource(bookID string, path string, src []byte) (def *AppletDef, err error)

ParseDocSource parses one applet document from raw markdown — the shared core behind the committed-book path and the runtime store's save gate (ADR-0132 Update "O4"): both submit the identical document shape and are judged by the identical rules. A nil def with a nil error is a prose page.

type EmbedConfig added in v0.0.15

type EmbedConfig struct {
	// StampAppId is the identity the log_comment stamp attributes runs to.
	// A standalone applet passes its minted manifest id; an embedder passes
	// a composed stamp — its own app id carrying the applet slug — so
	// per-applet attribution survives embedding (ADR-0134 §SD7).
	StampAppId string
	// RunId is the runtime run identity for the stamp.
	RunId string
	// InstanceKey is the window the stamp attributes runs to (ADR-0191
	// §SD4). Zero for an embedder that mints no window keys, which stamps
	// run and app as before.
	InstanceKey uint64
	// Bus is the capability bus for SetCapabilities. An applet's declared
	// capabilities ride the embedder's manifest (§SD8), so this is the
	// embedder's bus.
	Bus app.BusI
	// Log is the instance logger.
	Log zerolog.Logger
	// EndpointURL overrides the resolved endpoint. Empty resolves from
	// def.Endpoint (introspection → LocalQueryEndpoint; default → env).
	EndpointURL string
	// Bindings maps each declared dataset alias to the ephemeral handle the
	// embedder published, applied pre-mount so the buffer's keelson('<alias>')
	// rewrites to the handle client-side (ADR-0134 §SD4).
	Bindings map[string]string
	// Rules is the gloss rule repository the instance is built over
	// (ADR-0186): the embedder's standing rules and catalog. Nil takes
	// play.DefaultRepository, so an applet host that registers no rule sets
	// of its own shares the deployment's.
	Rules *gloss.Repository
}

EmbedConfig carries the host-supplied collaborators NewEmbedded needs. It is the ADR-0132 §SD8 graduation surface: an embedder app hosts an applet document while every §SD1 invariant (committed, gated, classified buffer) survives (ADR-0134 §SD7).

type EndpointE

type EndpointE uint8

EndpointE selects the server an applet speaks to (ADR-0132 §SD7).

const (
	// EndpointDefault — the env-configured ClickHouse, exactly as play's own
	// launcher resolves it.
	EndpointDefault EndpointE = iota
	// EndpointIntrospection — the in-process ADR-0094 `/query` endpoint.
	// Parameter binding works there since ADR-0133 M3 (the chhttp dialect
	// plus the broker's SET-prelude channel); the remaining parity gaps are
	// read counters and progress headers, recorded in ADR-0133 §SD4.
	EndpointIntrospection
)

type StoreService

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

StoreService is the runtime applet store (ADR-0132 Update "O4"): it serves `applet.store.save`, validating each submitted document with the same parser the committed books go through, persisting it through the runtime persist facility, and minting its manifest live. It is the moderation gate between an authoring app and the launcher.

func StartStore

func StartStore(bus *inprocbus.Inst, logger zerolog.Logger) (svc *StoreService, err error)

StartStore loads the stored applet corpus, mints it into the default app registry, and subscribes the save endpoint. Call it once at startup, after MintManifests — committed books must already be minted so the collision rule ("curation outranks runtime state", O4-D3) can read the registry as the source of truth.

func (*StoreService) Stop

func (inst *StoreService) Stop()

Stop unsubscribes the save endpoint. Idempotent, nil-safe.

type TabSel

type TabSel struct {
	ID   string
	Node string
	// Zone is the pane's placement, empty for the panel's own default. See
	// [tabZones] for the three an author may name and why the other two are
	// not among them.
	Zone string
}

TabSel is one entry of an explicit frontmatter `tabs:` list: a result-panel slug, optionally bound to a split node by CTE name (`table:recent`, ADR-0132 §SD4 riding ADR-0097 slice 6c), and optionally placed in a layout zone (`table@bottom`, ADR-0132 Update 2026-08-14).

The full form is `<panel>[:<node>][@<zone>]`. The zone comes last because the node binding was there first and a suffix cannot be added in front of one without re-reading every existing document.

Jump to

Keyboard shortcuts

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