config

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Jul 24, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
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

func (c *APIConfig) GetCORSOrigins() []string

GetCORSOrigins returns the configured CORS origins, or nil if not configured

func (*APIConfig) GetMaxTrackedIPs

func (c *APIConfig) GetMaxTrackedIPs() int

GetMaxTrackedIPs returns the maximum number of unique IPs tracked by the rate limiter (default: 10000)

func (*APIConfig) GetRateLimitBurst

func (c *APIConfig) GetRateLimitBurst() int

GetRateLimitBurst returns the burst size (default: 20)

func (*APIConfig) GetRateLimitRPS

func (c *APIConfig) GetRateLimitRPS() float64

GetRateLimitRPS returns the rate limit in requests per second (default: 10)

func (*APIConfig) IsAuthEnabled

func (c *APIConfig) IsAuthEnabled() bool

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"`
	Navigation  []NavSection             `yaml:"navigation,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 DefaultConfig

func DefaultConfig() *Config

DefaultConfig returns the default configuration

func Load

func Load(configPath string) (*Config, error)

Load loads configuration from a YAML file If the file doesn't exist, returns the default configuration

func LoadFromDir

func LoadFromDir(dir string) (*Config, error)

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

func (c *Config) ApprovedAction(name string) bool

ApprovedAction reports whether name is an approved action.

func (*Config) ApprovedSource added in v0.4.0

func (c *Config) ApprovedSource(name string) bool

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

func (c *Config) EnforceApprovedAction(name string) error

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

func (c *Config) EnforceApprovedSource(name string) error

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

func (c *Config) IsAPIEnabled() bool

IsAPIEnabled returns whether the API is enabled

func (*Config) IsManifest added in v0.4.0

func (c *Config) IsManifest() bool

IsManifest reports whether this config declares a generation surface — i.e. whether approval semantics apply at all.

func (*Config) IsSiteMode

func (c *Config) IsSiteMode() bool

IsSiteMode returns true if the config is for a multi-page site

func (*Config) IsTutorialMode

func (c *Config) IsTutorialMode() bool

IsTutorialMode returns true if the config is for a single tutorial

func (*Config) Save

func (c *Config) Save(configPath string) error

Save writes the configuration to a YAML file

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

func (c *Config) ValidateActions() error

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

func (c *Config) ValidateGeneration() error

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

func (c *Config) ValidateOutputs() error

ValidateOutputs validates all output configurations in the config.

func (*Config) ValidateStyleTokens added in v0.4.0

func (c *Config) ValidateStyleTokens() error

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

func (c *Config) ValidateWebhooks() error

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 struct {
	Title     string    `yaml:"title"`               // Page or group title (e.g., "Installation", "Forms & Editing")
	Path      string    `yaml:"path,omitempty"`      // Page path (e.g., "getting-started/installation.md"); empty for a pure group
	Collapsed bool      `yaml:"collapsed,omitempty"` // For groups: whether collapsed by default
	Pages     []NavPage `yaml:"pages,omitempty"`     // Sub-pages; presence makes this a group
}

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 NavSection struct {
	Title     string    `yaml:"title"`           // Section title (e.g., "Getting Started")
	Path      string    `yaml:"path"`            // Section path (e.g., "getting-started")
	Collapsed bool      `yaml:"collapsed"`       // Whether section is collapsed by default
	Pages     []NavPage `yaml:"pages,omitempty"` // Pages in this section
}

NavSection represents a navigation section with pages

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")
	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

func (w *Webhook) GetSecret() string

GetSecret returns the webhook secret with environment variable expansion

func (*Webhook) GetSignatureSecret

func (w *Webhook) GetSignatureSecret() string

GetSignatureSecret returns the HMAC signature secret with environment variable expansion

func (*Webhook) GetTimestampTolerance

func (w *Webhook) GetTimestampTolerance() int

GetTimestampTolerance returns the timestamp tolerance in seconds (default 300)

func (*Webhook) Validate

func (w *Webhook) Validate(name string, actions map[string]*Action) error

Validate checks that the webhook configuration is valid. Returns an error if any validation fails.

Jump to

Keyboard shortcuts

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