Documentation
¶
Index ¶
- Variables
- func GetOperator() string
- func IsExecAllowed() bool
- func SetAllowExec(allow bool)
- func SetOperator(op string)
- type APIConfig
- type APIKeyConfig
- type Action
- type AuthConfig
- type BlocksConfig
- type CORSConfig
- type CacheConfig
- type Config
- func (c *Config) ApprovedAction(name string) bool
- func (c *Config) ApprovedSource(name string) bool
- func (c *Config) CheckPolicy(refs DocumentRefs) []PolicyViolation
- func (c *Config) EnforceApprovedAction(name string) error
- func (c *Config) EnforceApprovedSource(name string) error
- func (c *Config) IsAPIEnabled() bool
- func (c *Config) IsManifest() bool
- func (c *Config) IsSiteMode() bool
- func (c *Config) IsTutorialMode() bool
- func (c *Config) Save(configPath string) error
- func (c *Config) Summarize(refs DocumentRefs) *OperationSummary
- func (c *Config) ValidateActions() error
- func (c *Config) ValidateGeneration() error
- func (c *Config) ValidateOutputs() error
- func (c *Config) ValidateStyleTokens() error
- func (c *Config) ValidateWebhooks() error
- type DocumentRefs
- type FeaturesConfig
- type GenerationConfig
- type NavPage
- type NavSection
- type Operation
- type OperationSummary
- type OutputConfig
- type ParamDef
- type Permission
- type PolicyViolation
- type RateLimitConfig
- type RetryConfig
- type RouteEntry
- type RuntimeConfig
- type SecurityConfig
- type ServerConfig
- type SiteConfig
- type SourceConfig
- func (c SourceConfig) GetCacheMaxBytes() int
- func (c SourceConfig) GetCacheMaxRows() int
- func (c SourceConfig) GetCacheStrategy() string
- func (c SourceConfig) GetCacheTTL() time.Duration
- func (c SourceConfig) GetRetryBaseDelay() time.Duration
- func (c SourceConfig) GetRetryMaxDelay() time.Duration
- func (c SourceConfig) GetRetryMaxRetries() int
- func (c SourceConfig) GetTimeout() time.Duration
- func (c SourceConfig) IsCacheEnabled() bool
- func (c SourceConfig) IsReadonly() bool
- func (c SourceConfig) IsStaleWhileRevalidate() bool
- type StylingConfig
- type Webhook
Constants ¶
This section is empty.
Variables ¶
var KnownStyleTokens = map[string]string{
"bg_primary": "--bg-primary",
"bg_secondary": "--bg-secondary",
"text_primary": "--text-primary",
"text_secondary": "--text-secondary",
"text_heading": "--text-heading",
"border_color": "--border-color",
"accent": "--accent",
"card_bg": "--card-bg",
"card_border": "--card-border",
"card_shadow": "--card-shadow",
"code_bg": "--code-bg",
"code_border": "--code-border",
"pre_bg": "--pre-bg",
"pre_text": "--pre-text",
}
KnownStyleTokens maps each overridable design-token key (snake_case, as used in styling.tokens) to the CSS custom property it drives in the page's :root. This is the page-shell on-brand palette (server.go's :root); client-chrome tokens (search/tabs/toc) are internal and deliberately not author-facing.
Functions ¶
func GetOperator ¶
func GetOperator() string
GetOperator returns the current operator identity. Returns empty string if not set and $USER is not available.
func IsExecAllowed ¶
func IsExecAllowed() bool
IsExecAllowed returns whether exec actions are enabled.
func SetAllowExec ¶
func SetAllowExec(allow bool)
SetAllowExec enables or disables exec actions. Exec actions (shell commands) are disabled by default for security.
func SetOperator ¶
func SetOperator(op string)
SetOperator sets the operator identity for this session. If empty, defaults to the current user from $USER environment variable.
Types ¶
type APIConfig ¶
type APIConfig struct {
Enabled bool `yaml:"enabled"` // Enable REST API endpoints (default: false)
CORS *CORSConfig `yaml:"cors,omitempty"`
RateLimit *RateLimitConfig `yaml:"rate_limit,omitempty"`
Auth *AuthConfig `yaml:"auth,omitempty"`
}
APIConfig holds REST API configuration
func (*APIConfig) GetCORSOrigins ¶
GetCORSOrigins returns the configured CORS origins, or nil if not configured
func (*APIConfig) GetMaxTrackedIPs ¶
GetMaxTrackedIPs returns the maximum number of unique IPs tracked by the rate limiter (default: 10000)
func (*APIConfig) GetRateLimitBurst ¶
GetRateLimitBurst returns the burst size (default: 20)
func (*APIConfig) GetRateLimitRPS ¶
GetRateLimitRPS returns the rate limit in requests per second (default: 10)
func (*APIConfig) IsAuthEnabled ¶
IsAuthEnabled returns true if API authentication is configured. It checks the raw config value (not env-expanded) so that a configured but missing env var is treated as "auth intended" rather than silently disabled.
type APIKeyConfig ¶
type APIKeyConfig struct {
Name string `yaml:"name"`
Key string `yaml:"key"`
Permissions []Permission `yaml:"permissions,omitempty"`
}
APIKeyConfig represents a named API key with associated permissions.
func (*APIKeyConfig) HasPermission ¶
func (k *APIKeyConfig) HasPermission(perm Permission) bool
HasPermission checks if this key has a specific permission.
type Action ¶
type Action struct {
// Describes is a human-readable note about what running this action does. Same
// role as SourceConfig.Describes: it is what an operator reads when reviewing the
// privileged operations a generated app performs. See Config.Generation.
Describes string `yaml:"describes,omitempty"`
Kind string `yaml:"kind"` // Action kind: "sql", "http", "exec"
Source string `yaml:"source,omitempty"` // For sql: source name to execute against
Statement string `yaml:"statement,omitempty"` // For sql: a single SQL statement with :param placeholders
Statements []string `yaml:"statements,omitempty"` // For sql: several statements run atomically in one transaction (mutually exclusive with statement)
URL string `yaml:"url,omitempty"` // For http: request URL (supports template expressions)
Method string `yaml:"method,omitempty"` // For http: HTTP method (default: POST)
Body string `yaml:"body,omitempty"` // For http: request body template
Cmd string `yaml:"cmd,omitempty"` // For exec: command to run
Params map[string]ParamDef `yaml:"params,omitempty"` // Parameter definitions
Confirm string `yaml:"confirm,omitempty"` // Confirmation message (triggers dialog)
}
Action defines a custom action that can be triggered via lvt-click
type AuthConfig ¶
type AuthConfig struct {
// APIKey is the legacy single API key for authentication (backward compatible).
// Supports environment variable expansion (e.g., "${API_KEY}" or "$API_KEY").
// Gets full permissions (read, write, delete) when used.
APIKey string `yaml:"api_key,omitempty"`
// HeaderName is the HTTP header name for the API key (default: "X-API-Key")
// Also supports "Authorization: Bearer <token>" format when set to "Authorization"
HeaderName string `yaml:"header_name,omitempty"`
// Keys is a list of named API keys with specific permissions.
Keys []APIKeyConfig `yaml:"keys,omitempty"`
}
AuthConfig holds authentication configuration for the API
func (*AuthConfig) GetAPIKey ¶
func (c *AuthConfig) GetAPIKey() string
GetAPIKey returns the configured API key with environment variable expansion
func (*AuthConfig) GetAPIKeys ¶
func (c *AuthConfig) GetAPIKeys() []APIKeyConfig
GetAPIKeys returns all configured API keys, normalizing legacy and new formats. Legacy api_key gets full permissions for backward compatibility. Uses the raw (unexpanded) value to detect intent — if the user configured an api_key that expands to empty, auth is still enforced (rejecting all requests) rather than silently disabled.
func (*AuthConfig) GetHeaderName ¶
func (c *AuthConfig) GetHeaderName() string
GetHeaderName returns the header name for authentication (default: "X-API-Key")
type BlocksConfig ¶
type BlocksConfig struct {
AutoID bool `yaml:"auto_id"`
IDFormat string `yaml:"id_format"`
ShowLineNumbers bool `yaml:"show_line_numbers"`
}
BlocksConfig holds block-related configuration
type CORSConfig ¶
type CORSConfig struct {
Origins []string `yaml:"origins,omitempty"` // Allowed origins (e.g., ["http://localhost:3000", "*"])
}
CORSConfig holds CORS configuration for the API
type CacheConfig ¶
type CacheConfig struct {
TTL string `yaml:"ttl,omitempty"` // Cache TTL (e.g., "5m", "1h"). Default: disabled (empty)
Strategy string `yaml:"strategy,omitempty"` // Cache strategy: "simple" or "stale-while-revalidate". Default: "simple"
MaxRows int `yaml:"max_rows,omitempty"` // Maximum rows to cache (truncates if exceeded). Default: unlimited
MaxBytes int `yaml:"max_bytes,omitempty"` // Maximum bytes to cache (truncates if exceeded). Default: unlimited
}
CacheConfig configures caching behavior for a source
type Config ¶
type Config struct {
Title string `yaml:"title"`
Description string `yaml:"description"`
Type string `yaml:"type"` // "tutorial" or "site"
Site *SiteConfig `yaml:"site,omitempty"`
Server ServerConfig `yaml:"server"`
Styling StylingConfig `yaml:"styling"`
Blocks BlocksConfig `yaml:"blocks"`
Features FeaturesConfig `yaml:"features"`
Ignore []string `yaml:"ignore"`
Sources map[string]SourceConfig `yaml:"sources,omitempty"`
Actions map[string]*Action `yaml:"actions,omitempty"`
API *APIConfig `yaml:"api,omitempty"`
Webhooks map[string]*Webhook `yaml:"webhooks,omitempty"`
Outputs map[string]*OutputConfig `yaml:"outputs,omitempty"`
Security SecurityConfig `yaml:"security,omitempty"`
// Generation, when present, declares which of this project's sources and actions
// an LLM is allowed to wire up when generating an app. Its presence is what makes
// a tinkerdown.yaml a *manifest*; without it nothing here changes and the project
// behaves exactly as before.
Generation *GenerationConfig `yaml:"generation,omitempty"`
// VersionPrefix, when non-empty, becomes a URL path segment that is
// stripped from incoming requests before route resolution. Routes serve
// equivalently with or without the prefix; the prefix exists so that a
// future multi-version deployment can mount several site builds under
// distinct prefixes (e.g. /v0/, /latest/) without collision.
VersionPrefix string `yaml:"version_prefix,omitempty"`
// Routes declares custom URL routes that bypass the markdown page
// resolver. Each entry binds a request-path pattern to an upstream
// destination. Currently only `type: proxy` is supported, which
// reverse-proxies the request (including WebSocket upgrades) to the
// configured upstream host. The full request path is forwarded
// unchanged — the upstream is responsible for its own URL structure.
Routes []RouteEntry `yaml:"routes,omitempty"`
}
Config represents the tinkerdown configuration
func Load ¶
Load loads configuration from a YAML file If the file doesn't exist, returns the default configuration
func LoadFromDir ¶
LoadFromDir looks for tinkerdown.yaml, lmt.yaml, or livemdtools.yaml in the given directory tinkerdown.yaml is checked first, then lmt.yaml (short form), then livemdtools.yaml (legacy) If none is found, returns the default configuration
func (*Config) ApprovedAction ¶ added in v0.4.0
ApprovedAction reports whether name is an approved action.
func (*Config) ApprovedSource ¶ added in v0.4.0
ApprovedSource reports whether name is an approved source. Always false when the project declares no generation block, so callers need no presence check of their own.
func (*Config) CheckPolicy ¶ added in v0.4.0
func (c *Config) CheckPolicy(refs DocumentRefs) []PolicyViolation
CheckPolicy reports every way a document steps outside this project's approved surface. It returns nothing when the project declares no generation block: approval is opt-in, and a project without a manifest has no approved set to violate.
Two distinct checks, because two distinct things can be wrong:
- A *reference* to an unapproved name reaches outside the approved surface.
- A *declaration* of an unapproved name brings its own. Checking only references would miss this entirely — a document that declares `evil` and then references `evil` references only names it defined, so every reference resolves and the document looks clean.
Shadowing — declaring a name that *is* approved — is reported but is not a security boundary here. Precedence already pins approved names at runtime, so the declaration is inert. The diagnostic exists so a generating agent learns why its definition had no effect, rather than silently producing a document whose frontmatter is ignored.
func (*Config) EnforceApprovedAction ¶ added in v0.4.0
EnforceApprovedAction is the runtime gate for invoking a custom action: it rejects an action outside the approved set, so a running app — or a webhook / crafted-message caller — cannot invoke something the operator never approved, even though the generation-time lint already checked the document. It gates only on the action name, NOT the action's source: an approved action may legitimately target a writable store deliberately kept out of the approved *source* set (unbindable by any generated app). Returns nil when the project declares no generation block — approval is opt-in, mirroring the lint.
func (*Config) EnforceApprovedSource ¶ added in v0.4.0
EnforceApprovedSource is the runtime gate for a builtin write (add/delete/ toggle/update), which operates on the block's *bound* source: it rejects a write to a source outside the approved set. A manifest app can only bind an approved source (the lint enforces that at generation time), so this is defense-in-depth against a document that bound one anyway. Returns nil when the project declares no generation block.
func (*Config) IsAPIEnabled ¶
IsAPIEnabled returns whether the API is enabled
func (*Config) IsManifest ¶ added in v0.4.0
IsManifest reports whether this config declares a generation surface — i.e. whether approval semantics apply at all.
func (*Config) IsSiteMode ¶
IsSiteMode returns true if the config is for a multi-page site
func (*Config) IsTutorialMode ¶
IsTutorialMode returns true if the config is for a single tutorial
func (*Config) Summarize ¶ added in v0.4.0
func (c *Config) Summarize(refs DocumentRefs) *OperationSummary
Summarize describes what a document does with the approved surface it uses.
Only approved names are described. An unapproved name is a policy violation, and the lint reports it as such — summarizing it here would present something the document may not do as though it were part of the plan.
Returns nil when the project declares no generation block: without an approved surface there is no operator review step for a summary to feed.
func (*Config) ValidateActions ¶ added in v0.4.0
ValidateActions checks that every sql action is executable as written. A sql action carries either a single `statement` or a `statements` batch (run atomically in one transaction), never both and never neither: both is ambiguous, neither is a no-op that would fail silently at click time rather than loudly at load.
func (*Config) ValidateGeneration ¶ added in v0.4.0
ValidateGeneration checks that every approved name refers to something this project actually declares.
This is not tidiness. Approval is what pins a source or action against redefinition by page frontmatter, so an approved name with no definition behind it does not fail loudly — it simply never pins anything, leaving that name shadowable. A typo in `generation.sources` would therefore *remove* a protection while looking like it added one. Failing at load makes that impossible.
func (*Config) ValidateOutputs ¶
ValidateOutputs validates all output configurations in the config.
func (*Config) ValidateStyleTokens ¶ added in v0.4.0
ValidateStyleTokens rejects any styling.tokens key that is not a known design token, so a typo fails loudly at load rather than silently skinning nothing.
func (*Config) ValidateWebhooks ¶
ValidateWebhooks validates all webhook configurations in the config. Returns an error if any webhook has invalid configuration.
type DocumentRefs ¶ added in v0.4.0
type DocumentRefs struct {
Sources []string
Actions []string
DeclaredSources []string
DeclaredActions []string
}
DocumentRefs is what a policy check needs to know about a document: the names it reaches for, and the names it brought itself.
This mirrors tinkerdown.DocRefs. It is redeclared here so the config package — which owns the approved set — does not import the root package that produces the refs.
type FeaturesConfig ¶
type FeaturesConfig struct {
HotReload bool `yaml:"hot_reload"`
Sidebar bool `yaml:"sidebar"` // Show navigation sidebar (default: false)
Headless bool `yaml:"headless"` // Run without web UI, only API/webhooks/schedules
// PrerenderDiagrams enables server-side mermaid pre-rendering via
// Kroki. When true, “`mermaid blocks are converted to inline SVG at
// parse time and the ~3.3MB client-side mermaid runtime is skipped on
// pages where ALL blocks pre-rendered successfully. Blocks that fail
// to render fall back to the client-side runtime. Default: false.
PrerenderDiagrams bool `yaml:"prerender_diagrams,omitempty"`
// KrokiURL overrides the Kroki base URL used for diagram pre-render
// (default: https://kroki.io public instance). Point this at a
// self-hosted Kroki container for production deployments where the
// public instance's rate limits or terms are not acceptable.
KrokiURL string `yaml:"kroki_url,omitempty"`
}
FeaturesConfig holds feature flags
type GenerationConfig ¶ added in v0.4.0
type GenerationConfig struct {
// Sources names the sources a generated app may bind to. Each must exist in
// Config.Sources; naming an undefined source is a config error, not a silent skip.
Sources []string `yaml:"sources,omitempty"`
// Actions names the actions a generated app may invoke. Each must exist in
// Config.Actions.
Actions []string `yaml:"actions,omitempty"`
// StyleGuide optionally points at a markdown file describing house style — tone,
// layout conventions, which components to prefer, what to avoid — injected into
// the generation context so output conforms by construction. Optional: without it
// generation falls back to the project theme and PicoCSS semantic defaults.
StyleGuide string `yaml:"style_guide,omitempty"`
}
GenerationConfig declares the surface an LLM may wire up when generating an app against this project — the "approved set".
Approval is enforced in two places, doing two different jobs:
- At runtime, by precedence: an approved name is pinned, so a generated page's frontmatter cannot redefine it to mean something else. Frontmatter can declare sources and actions freely (page.go MergeFromFrontmatter), which would otherwise let a generated doc shadow an approved name — reference `requests`, but define `requests` as something the operator never approved.
- At generation time, by `tinkerdown validate`, which reports references to and declarations of names outside this set so a generating agent can self-correct.
Precedence is the guarantee; the lint is the feedback. Neither substitutes for the other, and the lint deliberately does not re-implement the pin.
Absent this block, precedence is the long-standing two-tier rule (frontmatter wins, config provides defaults) and no lint runs.
type NavPage ¶
type NavPage struct {
}
NavPage represents a single entry in navigation. It is either a leaf (Path set, no Pages) or a collapsible group (Pages set) — or both, a landing page that also owns sub-pages. Groups let a long section nest its pages by category instead of rendering as one flat list.
type Operation ¶ added in v0.4.0
type Operation struct {
Kind string `json:"kind"` // "source" or "action"
Name string `json:"name"` //
Type string `json:"type"` // source type, or action kind
Describes string `json:"describes,omitempty"` // the manifest's human-readable note
Execs bool `json:"execs,omitempty"` // runs a shell command
Writes bool `json:"writes,omitempty"` // mutates stored data
Network bool `json:"network,omitempty"` // talks to something off-host
}
Operation is one privileged thing a document does: a source it reads or an action it runs, described in terms an operator can judge.
type OperationSummary ¶ added in v0.4.0
type OperationSummary struct {
Privileged bool `json:"privileged"`
Operations []Operation `json:"operations"`
}
OperationSummary is what a document does with its approved surface, in a form an operator can review before it is served.
Privileged carries the proportionality rule. A console that only reads is not worth interrupting anyone over; one that executes shell commands, writes data, or reaches the network is. The distinction exists so review attention is spent where it matters — a prompt shown for every generated page is a prompt nobody reads.
type OutputConfig ¶
type OutputConfig struct {
// Type is the output type: "slack" or "email"
Type string `yaml:"type"`
// Channel is the Slack channel (for slack type), e.g., "#team-updates"
// Environment variable expansion is supported (e.g., "${SLACK_CHANNEL}")
Channel string `yaml:"channel,omitempty"`
// To is the email recipient address (for email type)
// Environment variable expansion is supported (e.g., "${ALERT_EMAIL}")
To string `yaml:"to,omitempty"`
// Subject is the email subject line (for email type)
// Defaults to "Notification from Tinkerdown"
Subject string `yaml:"subject,omitempty"`
}
OutputConfig defines an output destination for notifications. Outputs receive messages from Notify imperatives in markdown content.
Example Configuration ¶
outputs:
team-slack:
type: slack
channel: "#team-updates"
alerts-email:
type: email
to: "alerts@company.com"
subject: "Tinkerdown Alert"
func (*OutputConfig) GetChannel ¶
func (o *OutputConfig) GetChannel() string
GetChannel returns the channel with environment variable expansion
func (*OutputConfig) GetTo ¶
func (o *OutputConfig) GetTo() string
GetTo returns the recipient address with environment variable expansion
func (*OutputConfig) Validate ¶
func (o *OutputConfig) Validate(name string) error
Validate checks that the output configuration is valid.
type ParamDef ¶
type ParamDef struct {
Type string `yaml:"type,omitempty"` // Parameter type: "string", "number", "date", "bool"
Required bool `yaml:"required,omitempty"` // Whether the parameter is required
Default string `yaml:"default,omitempty"` // Default value
}
ParamDef defines a parameter for an action
type Permission ¶
type Permission string
Permission represents an API operation permission.
const ( PermRead Permission = "read" PermWrite Permission = "write" PermDelete Permission = "delete" )
type PolicyViolation ¶ added in v0.4.0
type PolicyViolation struct {
Kind string // "source" or "action"
Name string // the offending name
Reason string // what is wrong
Hint string // what to do instead
Shadows bool // the name is approved, and the document tried to redefine it
}
PolicyViolation is one way a document steps outside the approved surface.
func (PolicyViolation) Error ¶ added in v0.4.0
func (v PolicyViolation) Error() string
type RateLimitConfig ¶
type RateLimitConfig struct {
RequestsPerSecond float64 `yaml:"requests_per_second,omitempty"` // Rate limit in requests per second (default: 10)
Burst int `yaml:"burst,omitempty"` // Burst size (default: 20)
MaxTrackedIPs int `yaml:"max_tracked_ips,omitempty"` // Maximum unique IPs to track (default: 10000)
}
RateLimitConfig holds rate limiting configuration for the API
type RetryConfig ¶
type RetryConfig struct {
MaxRetries int `yaml:"max_retries,omitempty"` // Maximum retry attempts (default: 3)
BaseDelay string `yaml:"base_delay,omitempty"` // Initial delay (e.g., "100ms"). Default: 100ms
MaxDelay string `yaml:"max_delay,omitempty"` // Maximum delay (e.g., "5s"). Default: 5s
}
RetryConfig configures retry behavior for a source
type RouteEntry ¶
type RouteEntry struct {
Pattern string `yaml:"pattern"`
Type string `yaml:"type"`
Upstream string `yaml:"upstream"`
}
RouteEntry binds a URL pattern to a destination. A pattern ending in "/" matches that subtree; otherwise it must match exactly. Routes are evaluated in declaration order; first match wins.
type RuntimeConfig ¶
type RuntimeConfig struct {
// contains filtered or unexported fields
}
RuntimeConfig stores configuration set at runtime via CLI flags. These values are not persisted to config files.
type SecurityConfig ¶ added in v0.1.16
type SecurityConfig struct {
// FrameSrc lists origins appended to the CSP frame-src directive,
// in addition to the implicit 'self'. Set this when the site embeds
// cross-origin iframes (e.g., a separately-deployed app loaded as a
// live demo on a docs page). Validate() rejects entries that contain
// CSP/header-injection characters or that don't parse as a URI. Use
// scheme + host (e.g., "https://lt-landing-demo.fly.dev"). When the
// list is empty no frame-src directive is emitted, falling back to
// default-src 'self' which blocks cross-origin frames.
FrameSrc []string `yaml:"frame_src,omitempty"`
}
SecurityConfig exposes site-level security knobs that change emitted security response headers. Currently scoped to CSP overrides; further fields can be added without breaking existing configs because the struct is yaml-omitempty.
func (SecurityConfig) Validate ¶ added in v0.1.16
func (c SecurityConfig) Validate() error
Validate ensures every FrameSrc entry is safe to emit verbatim into a CSP header value. CSP directives are separated by `;`, and HTTP header values must not contain CR/LF, so any of those characters in an operator-supplied origin would either smuggle a new directive (e.g., widening script-src) or split the response header entirely. URL parsing additionally rejects obviously malformed values so that a typo surfaces at startup instead of as a silently-broken iframe.
type ServerConfig ¶
type ServerConfig struct {
Port int `yaml:"port"`
Host string `yaml:"host"`
Debug bool `yaml:"debug"`
}
ServerConfig holds server-related configuration
type SiteConfig ¶
type SiteConfig struct {
Home string `yaml:"home"` // Homepage markdown file (e.g., "index.md")
Logo string `yaml:"logo"` // Logo path (e.g., "/assets/logo.svg")
Repository string `yaml:"repository"` // GitHub repository URL
// URL is the canonical absolute base URL of the deployed site
// (e.g., "https://livetemplate.fly.dev"), with NO trailing slash.
// When set, sitemap.xml emits absolute URLs and OpenGraph meta tags
// include og:url. When empty, sitemap entries use relative paths and
// og:url is omitted.
URL string `yaml:"url,omitempty"`
}
SiteConfig holds site-level configuration
type SourceConfig ¶
type SourceConfig struct {
// Describes is a human-readable note about what this source touches — the
// dataset, its scope, its sensitivity. It carries no runtime behavior; it exists
// so an operator reviewing what a generated app does sees "the pending PII access
// requests queue" rather than a table name. See Config.Generation.
Describes string `yaml:"describes,omitempty"`
Type string `yaml:"type"` // "exec", "pg", "rest", "csv", "json", "markdown", "sqlite", "wasm", "graphql"
Cmd string `yaml:"cmd,omitempty"` // For exec: command to run
Query string `yaml:"query,omitempty"` // For pg: SQL query
From string `yaml:"from,omitempty"` // For rest/graphql: API endpoint URL
File string `yaml:"file,omitempty"` // For csv/json/markdown: file path
Anchor string `yaml:"anchor,omitempty"` // For markdown: section anchor (e.g., "#todos")
DB string `yaml:"db,omitempty"` // For sqlite: database file path (default: ./tinkerdown.db)
Table string `yaml:"table,omitempty"` // For sqlite: table name
Path string `yaml:"path,omitempty"` // For wasm: path to .wasm file
QueryFile string `yaml:"query_file,omitempty"` // For graphql: path to .graphql file
Variables map[string]interface{} `yaml:"variables,omitempty"` // For graphql: query variables
Headers map[string]string `yaml:"headers,omitempty"` // For rest/graphql: HTTP headers (env vars expanded)
QueryParams map[string]string `yaml:"query_params,omitempty"` // For rest: URL query parameters (env vars expanded)
ResultPath string `yaml:"result_path,omitempty"` // For rest/graphql: dot-path to extract array (e.g., "data.items")
Readonly *bool `yaml:"readonly,omitempty"` // For markdown/sqlite: read-only mode (default: true, set to false for writes)
Options map[string]string `yaml:"options,omitempty"` // Type-specific options (also used for wasm init config)
Manual bool `yaml:"manual,omitempty"` // For exec: require Run button click
Format string `yaml:"format,omitempty"` // For exec: output format (json, lines, csv). Default: json
Delimiter string `yaml:"delimiter,omitempty"` // For exec CSV: field delimiter. Default: ","
Env map[string]string `yaml:"env,omitempty"` // For exec: environment variables (env vars expanded)
Timeout string `yaml:"timeout,omitempty"` // Request timeout (e.g., "30s", "1m"). Default: 10s
Retry *RetryConfig `yaml:"retry,omitempty"` // Retry configuration
Cache *CacheConfig `yaml:"cache,omitempty"` // Cache configuration
AutoBind *bool `yaml:"auto_bind,omitempty"` // Set to false to exclude from auto-table matching
// For computed sources: derive data from another source
GroupBy string `yaml:"group_by,omitempty"` // Field to group by (e.g., "category")
Aggregate map[string]string `yaml:"aggregate,omitempty"` // Field → aggregation expression (e.g., "total": "sum(amount)")
Filter string `yaml:"filter,omitempty"` // Optional filter expression (e.g., "status = active")
}
SourceConfig defines a data source for lvt-source blocks
func (SourceConfig) GetCacheMaxBytes ¶
func (c SourceConfig) GetCacheMaxBytes() int
GetCacheMaxBytes returns the max bytes limit (0 = unlimited)
func (SourceConfig) GetCacheMaxRows ¶
func (c SourceConfig) GetCacheMaxRows() int
GetCacheMaxRows returns the max rows limit (0 = unlimited)
func (SourceConfig) GetCacheStrategy ¶
func (c SourceConfig) GetCacheStrategy() string
GetCacheStrategy returns the cache strategy (default: "simple")
func (SourceConfig) GetCacheTTL ¶
func (c SourceConfig) GetCacheTTL() time.Duration
GetCacheTTL returns the cache TTL (0 if caching is disabled)
func (SourceConfig) GetRetryBaseDelay ¶
func (c SourceConfig) GetRetryBaseDelay() time.Duration
GetRetryBaseDelay returns the base delay (default: 100ms)
func (SourceConfig) GetRetryMaxDelay ¶
func (c SourceConfig) GetRetryMaxDelay() time.Duration
GetRetryMaxDelay returns the max delay (default: 5s)
func (SourceConfig) GetRetryMaxRetries ¶
func (c SourceConfig) GetRetryMaxRetries() int
GetRetryMaxRetries returns the max retries (default: 3, set to 0 to disable retries)
func (SourceConfig) GetTimeout ¶
func (c SourceConfig) GetTimeout() time.Duration
GetTimeout returns the parsed timeout duration (default: 10s)
func (SourceConfig) IsCacheEnabled ¶
func (c SourceConfig) IsCacheEnabled() bool
IsCacheEnabled returns true if caching is enabled for this source
func (SourceConfig) IsReadonly ¶
func (c SourceConfig) IsReadonly() bool
IsReadonly returns true if the source is read-only (default: true for markdown sources)
func (SourceConfig) IsStaleWhileRevalidate ¶
func (c SourceConfig) IsStaleWhileRevalidate() bool
IsStaleWhileRevalidate returns true if using stale-while-revalidate strategy
type StylingConfig ¶
type StylingConfig struct {
Theme string `yaml:"theme"`
PrimaryColor string `yaml:"primary_color"`
Font string `yaml:"font"`
// CustomCSS is a site-relative path (e.g. "assets/landing.css") served
// from <rootDir>/assets and injected as a <link> in the <head> of pages
// using `layout: landing`. Lets a site carry bespoke styling for its
// marketing/landing pages without touching the default docs shell.
CustomCSS string `yaml:"custom_css,omitempty"`
// SiteCSS is a site-relative path served from <rootDir>/assets and injected
// as a <link> in the <head> of EVERY page (both the default docs shell and
// `layout: landing`). Use it for shared brand primitives — self-hosted
// @font-face declarations, base tokens — that should reach the calm docs
// shell too, while CustomCSS stays quarantined to landing pages. On landing
// pages SiteCSS loads before CustomCSS so the landing layer can override it.
SiteCSS string `yaml:"site_css,omitempty"`
// Tokens overrides individual design tokens — the on-brand palette — declaratively,
// so a team sets its brand without writing raw CSS. Keys are the snake_case names
// in KnownStyleTokens (e.g. "accent", "bg_primary", "card_bg"); each drives the
// matching CSS custom property (--accent, --bg-primary, …) in the page's :root,
// overriding the built-in default via the same mechanism primary_color uses for
// --accent. Overriding a token skins the generated (semantic) HTML on-brand by
// construction. An unknown key is a config error (ValidateStyleTokens). Absent,
// the built-in defaults apply.
Tokens map[string]string `yaml:"tokens,omitempty"`
}
StylingConfig holds styling-related configuration
type Webhook ¶
type Webhook struct {
// Action is the name of the action to execute when this webhook is triggered
Action string `yaml:"action"`
// Secret is the shared secret for validation (supports env var expansion)
// Used for X-Webhook-Secret header or ?secret= query param validation
Secret string `yaml:"secret,omitempty"`
// SignatureSecret is the secret used for HMAC signature validation (supports env var expansion)
// When set, validates X-Webhook-Signature header in format "sha256=<hex>"
// This provides stronger security than plain secret validation
SignatureSecret string `yaml:"signature_secret,omitempty"`
// ValidateTimestamp enables replay attack prevention by validating X-Webhook-Timestamp
// Requests older than TimestampTolerance seconds are rejected
ValidateTimestamp bool `yaml:"validate_timestamp,omitempty"`
// TimestampTolerance is the maximum age in seconds for timestamp validation (default: 300 = 5 minutes)
TimestampTolerance int `yaml:"timestamp_tolerance,omitempty"`
}
Webhook defines a webhook trigger that can receive HTTP POST requests.
Webhooks allow external services (CI/CD, monitoring, etc.) to trigger actions by sending POST requests to /webhook/{name} endpoints.
Security Features ¶
Webhooks support multiple authentication methods:
- Simple secret: X-Webhook-Secret header or ?secret= query parameter
- HMAC signature: X-Webhook-Signature header with "sha256=<hex>" format
- Timestamp validation: X-Webhook-Timestamp header for replay attack prevention
Exec Action Restrictions ¶
When a webhook triggers an "exec" action, the command is validated for safety. The following shell metacharacters are blocked to prevent command injection:
- & ; | : command chaining/background execution
- $ : variable expansion (could leak environment variables)
- > < : redirection (could overwrite files)
- ` : command substitution
- \ : escape sequences
- \n \r : newlines (could inject additional commands)
For complex commands, create an intermediate script and invoke it via the webhook.
Example Configuration ¶
webhooks:
deploy:
action: deploy-app
signature_secret: ${WEBHOOK_SECRET}
validate_timestamp: true
timestamp_tolerance: 300
github-push:
action: sync-repo
secret: ${GITHUB_WEBHOOK_SECRET}
func (*Webhook) GetSecret ¶
GetSecret returns the webhook secret with environment variable expansion
func (*Webhook) GetSignatureSecret ¶
GetSignatureSecret returns the HMAC signature secret with environment variable expansion
func (*Webhook) GetTimestampTolerance ¶
GetTimestampTolerance returns the timestamp tolerance in seconds (default 300)