Documentation
¶
Index ¶
- Constants
- func LoadLanguages(cfg *Config) ([]string, error)
- func LoadPostTypes(cfg *Config) (*posttype.Service, error)
- func LoadRoles(cfg *Config, postTypes []string) (*role.Service, error)
- func LoadThumbnails(cfg *Config) (*thumbnail.Service, error)
- func PrimaryLanguage(languages []string) string
- type CSPConfig
- type CommentsConfig
- type Config
- type HeadlessConfig
- type HomepageSection
- type ModulesConfig
- type PublicField
- type PublicFieldRegistry
- type RegistrationConfig
- type SiteConfig
Constants ¶
const ( // PublicFieldResourceUser and PublicFieldResourceContent are the two supported // values for PublicField.Resource. They map to the two public query endpoints: // the authors endpoint (users) and the content_items endpoint (content). PublicFieldResourceUser = "user" PublicFieldResourceContent = "content" // PublicFieldOperationSort, PublicFieldOperationFilter, and // PublicFieldOperationExpose are the supported values for PublicField.Operations. // A field can be allowlisted for any combination. PublicFieldOperationSort = "sort" PublicFieldOperationFilter = "filter" PublicFieldOperationExpose = "expose" )
Variables ¶
This section is empty.
Functions ¶
func LoadLanguages ¶
LoadLanguages loads the supported languages from the config.toml file. Returns at least ["en"] — if the config file is missing or has no languages defined, "en" is used as the primary language.
func LoadPostTypes ¶
LoadPostTypes loads custom post types from the config directory If the config file doesn't exist, it returns a service with default post types
func LoadRoles ¶ added in v0.10.0
LoadRoles loads custom [role] definitions from the same config.toml that supplies post types. The built-in roles (Admin, Contributor, Commentator) are always present; a same-name [role] entry overrides a built-in (except Admin). postTypes must list every registered post-type slug — custom entries may only reference existing types, so a typo fails closed at startup instead of silently granting a role an unregistered type. A missing config file or directory yields a service with only the built-in roles.
func LoadThumbnails ¶
LoadThumbnails loads thumbnail configurations from the config file (config.toml). If the file does not exist, it returns a service with default configs.
func PrimaryLanguage ¶
PrimaryLanguage returns the first language in the slice, or "en" if empty.
Types ¶
type CSPConfig ¶ added in v0.7.0
type CSPConfig struct {
Disable bool `toml:"disable"`
ReportOnly bool `toml:"report_only"`
ScriptSrc []string `toml:"script_src"`
StyleSrc []string `toml:"style_src"`
ImgSrc []string `toml:"img_src"`
FontSrc []string `toml:"font_src"`
ConnectSrc []string `toml:"connect_src"`
FrameSrc []string `toml:"frame_src"`
MediaSrc []string `toml:"media_src"`
ObjectSrc []string `toml:"object_src"`
WorkerSrc []string `toml:"worker_src"`
FrameAncestors []string `toml:"frame_ancestors"`
ExtraDirectives map[string]string `toml:"extra_directives"`
Policy string `toml:"policy"`
}
CSPConfig holds the optional [csp] block from config.toml. All fields have zero-value defaults that are backward compatible. Operators append sources to individual directives; they never replace. The exceptions are `policy` (full replacement) and `frame_ancestors` (replaces the `frame-ancestors` directive — appending to the default `'none'` is meaningless per the CSP spec, so this directive is a dedicated opt-in knob; it also drives the X-Frame-Options header, see XFrameOptions).
func LoadCSPConfig ¶ added in v0.7.0
LoadCSPConfig reads the optional [csp] block from config.toml. When the file, section, or directory is missing it returns a zero-value CSPConfig (fully backward compatible — Build() returns the default policy).
func (CSPConfig) Build ¶ added in v0.7.0
Build returns the CSP header name and value for this configuration. Empty header value means "do not emit a CSP header".
func (CSPConfig) IFrameHosts ¶ added in v0.10.0
IFrameHosts derives the HTML sanitizer's iframe host allowlist from the frame-src directive: the built-in default sources plus operator appends. A full [csp] policy override replaces the defaults: the frame-src sources are parsed from that policy and used instead, mirroring the emitted header — an override without frame-src leaves the allowlist empty so iframes stay stripped. disable and report_only keep the default-based allowlist so the sanitizer stays a restrictive safety net even when the browser gate is off. Non-host sources ("'self'", bare schemes) are skipped; "*.host" entries keep their wildcard prefix so the sanitizer allows only subdomains. The result feeds sanitize.SanitizeHTMLDocument so embeds the CSP allows to be framed are also allowed through the sanitizer.
func (CSPConfig) XFrameOptions ¶ added in v0.10.0
XFrameOptions derives the X-Frame-Options header value from the framing configuration so the legacy header can never contradict the CSP. A policy override owns the framing story when set (mirroring Build — the knob only applies without a policy). Rules:
- a frame-ancestors source list that is exactly "'self'" → "SAMEORIGIN" (duplicates and case variants included; "'self'" is the only keyword X-Frame-Options can express)
- any "'none'" source → "DENY" (even in a mixed list, which browsers discard — the legacy header then holds the line)
- a host source list → "" (the header is omitted; frame-ancestors is the control). Exception: under report_only the CSP is not enforced, so a host list floors to "DENY" to keep a restriction in place during rollout trials; under disable the operator manages CSP at the edge and the omission stands (documented).
type CommentsConfig ¶ added in v0.9.0
type CommentsConfig struct {
Enabled *bool `toml:"enabled"`
}
CommentsConfig is the optional [comments] block from config.toml. When disabled, the comment system is hard-disabled: comment routes are not mounted, the admin UI hides all comment surfaces, new content defaults to allowComments=false, and self-registration (which creates Commentator users) is blocked. An absent block yields a zero-value CommentsConfig, which IsEnabled treats as enabled — the backward-compatible default.
func LoadComments ¶ added in v0.9.0
func LoadComments(cfg *Config) (CommentsConfig, error)
LoadComments reads the optional [comments] block from the same config.toml that supplies post types and homepage sections. It mirrors LoadHomepageSections: a missing config directory or file yields a zero-value CommentsConfig (which IsEnabled reports as enabled — fully backward compatible).
func (CommentsConfig) IsEnabled ¶ added in v0.9.0
func (c CommentsConfig) IsEnabled() bool
IsEnabled reports whether comments are enabled. The zero value (absent block or absent key) means enabled, so existing deployments without a [comments] block keep their comment system.
type Config ¶
type Config struct {
Host string
Port int
DBPath string
DBDriver string
DBDSN string
DBPoolMaxConns int
// StorageDriver selects the file storage backend: "local" (default) or "s3".
// The "s3" driver works against AWS S3 AND MinIO (both speak the S3 API).
// Read via STORAGE_DRIVER.
StorageDriver string
// StorageS3Endpoint is the S3-compatible endpoint URL (e.g. "http://minio:9000").
// Leave empty to use the default AWS endpoints. Read via STORAGE_S3_ENDPOINT.
StorageS3Endpoint string
// StorageS3Region is the AWS region or MinIO region (MinIO uses "us-east-1" by
// default). Read via STORAGE_S3_REGION.
StorageS3Region string
// StorageS3Bucket is the bucket media and profile pictures are stored in.
// Read via STORAGE_S3_BUCKET.
StorageS3Bucket string
// StorageS3AccessKeyID is the access key for the S3-compatible backend.
// Read via STORAGE_S3_ACCESS_KEY_ID.
StorageS3AccessKeyID string
// StorageS3SecretAccessKey is the secret key for the S3-compatible backend.
// Read via STORAGE_S3_SECRET_ACCESS_KEY.
StorageS3SecretAccessKey string
// StorageS3UsePathStyle forces path-style addressing ("bucket.example.com/key"
// vs "example.com/bucket/key"). Required for most MinIO deployments.
// Read via STORAGE_S3_USE_PATH_STYLE.
StorageS3UsePathStyle bool
// StorageS3PublicBaseURL is the base URL served to clients (the bucket's public
// URL or a CDN/CloudFront distribution, e.g. "https://cdn.example.com").
// GetURL returns this prefix + object key. Read via STORAGE_S3_PUBLIC_BASE_URL.
StorageS3PublicBaseURL string
JWTSecret string
LogLevel string
SMTPHost string
SMTPPort int
SMTPUser string
SMTPPassword string
SMTPFrom string
ConfigDir string
ConfigFile string
CORSAllowedOrigins string
SiteURL string
DevMode bool
AdminDevURL string
ThemeDir string
PostPerPage int
// ServerReadHeaderTimeout is the maximum duration to read request headers
// (Slowloris protection). Read via SERVER_READ_HEADER_TIMEOUT.
ServerReadHeaderTimeout time.Duration
// ServerReadTimeout is the maximum duration to read the entire request
// including the body. A zero value means no timeout — body size is capped
// per-handler via MaxBytesReader / maxBodySizeMiddleware. Read via
// SERVER_READ_TIMEOUT.
ServerReadTimeout time.Duration
// ServerWriteTimeout is the maximum duration to write the response after
// the request headers have been read. A zero value means no timeout. Read
// via SERVER_WRITE_TIMEOUT.
ServerWriteTimeout time.Duration
RateLimitEnabled bool
RateLimitAuthPerMinute int
RateLimitAPIPerMinute int
RateLimitPublicPerMinute int
AIImageGenerationAPIKey string
AIImageGenerationModel string
AIImageGenerationSize string
AIImageGenerationAspectRatio string
AITextGenerationAPIKey string
AITextGenerationBaseURL string
AITextGenerationModel string
APIKeyPepper string
// ImportMaxSizeMB is the ceiling (in megabytes) for any importer upload
// (WordPress WXR now; future importers reuse the same cap). Read via
// IMPORT_MAX_SIZE_MB. Use ImportMaxSize() for the byte value.
ImportMaxSizeMB int
// WordPressImportTimeout is the maximum duration a WordPress import job may
// run after the HTTP response has been sent (the job runs in a background
// goroutine). Read via WORDPRESS_IMPORT_TIMEOUT.
WordPressImportTimeout time.Duration
// HugoImportTimeout is the maximum duration a Hugo import job may run after
// the HTTP response has been sent (the job runs in a background goroutine).
// Read via HUGO_IMPORT_TIMEOUT.
HugoImportTimeout time.Duration
}
Config holds all application configuration
func Load ¶
Load loads configuration from environment variables It tries to load .env file first, then reads from actual environment
func (*Config) ImportMaxSize ¶ added in v0.5.0
ImportMaxSize returns the importer upload ceiling in bytes.
func (*Config) IsImageGenerationEnabled ¶
IsImageGenerationEnabled returns true if the Google Imagen API key is configured
func (*Config) IsTextGenerationEnabled ¶
IsTextGenerationEnabled returns true if the AI text generation API key is configured
func (*Config) ParseCORSOrigins ¶
ParseCORSOrigins parses the comma-separated CORS origins string into a slice It handles whitespace trimming and validates that each origin has a valid http/https scheme
type HeadlessConfig ¶ added in v0.9.0
type HeadlessConfig struct {
Enabled bool `toml:"enabled"`
}
HeadlessConfig is the optional [headless] block from config.toml. When Enabled is true, the server-rendered content site (the /* catch-all) is not mounted — the instance serves only the admin panel and the REST API, for headless CMS use. An absent block yields a zero-value HeadlessConfig (Enabled=false — the content site renders as before).
func LoadHeadless ¶ added in v0.9.0
func LoadHeadless(cfg *Config) (HeadlessConfig, error)
LoadHeadless reads the optional [headless] block from the same config.toml that supplies post types and homepage sections. It mirrors LoadHomepageSections: a missing config directory or file yields a zero-value HeadlessConfig (fully backward compatible).
type HomepageSection ¶ added in v0.5.0
type HomepageSection struct {
PostType string `toml:"post_type"`
Limit int `toml:"limit"`
Offset int `toml:"offset"`
Title string `toml:"title"`
}
HomepageSection is one [[homepage_section]] block from config.toml. It tells the public homepage to render a per-post-type grouping in addition to (or instead of relying on) the flat latest-posts list. PostType is the only required field; Limit, Offset, and Title are optional overrides.
func LoadHomepageSections ¶ added in v0.5.0
func LoadHomepageSections(cfg *Config) ([]HomepageSection, error)
LoadHomepageSections reads the [[homepage_section]] blocks from the same config.toml that supplies post types. It mirrors LoadPostTypes: a missing config directory or file yields an empty slice (the homepage then renders the flat latest-posts list — fully backward compatible).
type ModulesConfig ¶ added in v1.0.0
type ModulesConfig struct {
Disabled []string `toml:"disabled"`
}
ModulesConfig is the optional [modules] block from config.toml. Disabled names modules the composition root must not register: kernel.Prune drops them plus every transitive Requires dependent (cascade) before InitAll. Unknown names are warned about and ignored so configs stay portable across editions. An absent block yields a zero-value ModulesConfig (nothing disabled — the backward-compatible default). Headless mode is NOT expressed here: [headless] only suppresses public-surface mounting while the site-ssr engine stays registered for SSG/export.
func LoadModules ¶ added in v1.0.0
func LoadModules(cfg *Config) (ModulesConfig, error)
LoadModules reads the optional [modules] block from the same config.toml that supplies post types and homepage sections. It mirrors LoadHeadless: a missing config directory or file yields a zero-value ModulesConfig (fully backward compatible).
func (ModulesConfig) IsDisabled ¶ added in v1.0.0
func (c ModulesConfig) IsDisabled(name string) bool
IsDisabled reports whether the named module is disabled.
type PublicField ¶ added in v0.7.0
type PublicField struct {
Resource string `toml:"resource"`
Field string `toml:"field"`
PostType string `toml:"post_type"`
Operations []string `toml:"operations"`
}
PublicField is one [[public_field]] block from config.toml. It declares that a specific custom-field or system-field slug may be used in a public query (filter, sort, or expose) against one of the public query endpoints. Without an entry here, the public endpoints reject any cf_<field> / cf_<field>_min / cf_<field>_max / sort_by=cf:<field> parameter that references the field with a 400 field_not_queryable error. Fields with the "expose" operation are included in the response body (e.g. in the publicAuthors[:].publicFields map).
Admin endpoints (e.g. /api/v1/content_items) are NOT gated by this allowlist — they remain unrestricted, matching pre-existing behaviour.
type PublicFieldRegistry ¶ added in v0.7.0
type PublicFieldRegistry struct {
// contains filtered or unexported fields
}
PublicFieldRegistry is the immutable, lookup-optimised form of a slice of PublicField entries. Hand one of these to a handler and call IsQueryable to enforce the allowlist on incoming public queries.
func LoadPublicFields ¶ added in v0.7.0
func LoadPublicFields(cfg *Config) (*PublicFieldRegistry, error)
LoadPublicFields reads the [[public_field]] blocks from the same config.toml that supplies post types and homepage sections. It mirrors LoadSiteConfig: a missing config directory or file yields an empty registry (fully backward compatible — every public cf_*/sort_by=cf:* query is then rejected).
func (*PublicFieldRegistry) ExposedFields ¶ added in v0.7.0
func (r *PublicFieldRegistry) ExposedFields(resource, postType string) []string
ExposedFields returns the field slugs that are allowlisted with the "expose" operation for the given resource (and optionally postType). When resource is "content", postType is matched against the entry's PostType; an entry with an empty PostType matches every post type. When resource is "user", postType is ignored. An empty registry returns nil.
func (*PublicFieldRegistry) IsQueryable ¶ added in v0.7.0
func (r *PublicFieldRegistry) IsQueryable(resource, postType, field, operation string) bool
IsQueryable reports whether the named field may be used with the given operation against the named resource. When resource is "content", postType is matched against the entry's PostType; an entry with an empty PostType matches every post type. When resource is "user", postType is ignored.
An empty registry (no [[public_field]] blocks configured) returns false for every query — the public endpoints then reject every cf_*/sort_by=cf:* parameter. This is the safe default.
type RegistrationConfig ¶ added in v0.10.0
RegistrationConfig is the optional [registration] block from config.toml. It decouples self-registration from the comment system: today registration is enabled iff comments are enabled (because the only self-registerable role, Commentator, was meaningless without them). With custom [role] entries a site may want public registration for a non-comment role (e.g. a journalist role), so this block overrides the default coupling.
Email verification is always mandatory: registrants are always created "pending" and must verify their email address. AdminApproval adds a second activation layer on top of the email proof.
Absent block behavior (backward compatible):
- Enabled: follows the comment system (comments enabled ⇒ registration on).
- DefaultRole: "Commentator".
- AdminApproval: false (email verification activates the account).
func LoadRegistration ¶ added in v0.10.0
func LoadRegistration(cfg *Config) (RegistrationConfig, error)
LoadRegistration reads the optional [registration] block from the same config.toml that supplies post types. It mirrors LoadComments: a missing config directory or file yields a zero-value RegistrationConfig, whose IsEnabled(commentsEnabled) reproduces the legacy coupling.
func (RegistrationConfig) IsEnabled ¶ added in v0.10.0
func (c RegistrationConfig) IsEnabled(commentsEnabled bool) bool
IsEnabled reports whether self-registration is allowed. An explicit enabled key wins; otherwise it falls back to the comment system's state.
type SiteConfig ¶ added in v0.5.0
SiteConfig is the optional [site_config] block from config.toml. It carries the site's text and visual identity — the values that appear on every public page and that the handler otherwise bakes into the binary (notably the PageTitle suffix and the og:site_name). Both fields are optional; an absent block yields a zero-value SiteConfig, and the caller is expected to default Name to the application name when empty.
func LoadSiteConfig ¶ added in v0.5.0
func LoadSiteConfig(cfg *Config) (SiteConfig, error)
LoadSiteConfig reads the optional [site_config] block from the same config.toml that supplies post types and homepage sections. It mirrors LoadHomepageSections: a missing config directory or file yields a zero-value SiteConfig (fully backward compatible).