Documentation
¶
Overview ¶
Package registry loads the realm/database/collection tree from CONFIG_DIR into an immutable, validated registry used by routing, validation and provisioning.
Index ¶
- Constants
- Variables
- func NormalizeEmail(v string) (string, error)
- func ParseDuration(v string) (time.Duration, error)
- func ParseSize(v string) (int64, error)
- func SourceHash(dir string) (string, error)
- func ValidName(name string) bool
- func ValidSecretName(name string) bool
- type AccountSettings
- type Collection
- type Database
- type EmailLimits
- type EmailSettings
- type ErasurePolicy
- type Field
- type Function
- type Functions
- type Index
- type IndexKey
- type Manifest
- type ManifestBundle
- type Networks
- type RateLimit
- type Realm
- type RealmSettings
- type Registry
- func (r *Registry) AuthRealms() []string
- func (r *Registry) CheckBundles() error
- func (r *Registry) Collection(realm, database, collection string) (*Collection, bool)
- func (r *Registry) Databases() []*Database
- func (r *Registry) Fingerprint() (string, error)
- func (r *Registry) FunctionRealms(authEnabled bool) []string
- func (r *Registry) RealmNames() []string
- func (r *Registry) SortedRealms() []*Realm
- type Retry
- type Role
- type SecretRef
- type UserNetworks
Constants ¶
const ( ErasureDelete = "delete" ErasureAnonymize = "anonymize" )
Erasure actions on the documents a user owns.
const ( MatchEmail = "email" MatchID = "id" )
What a `pull` or `unset` field holds: the user's email or their id.
const ( FunctionsDir = "_functions" // one Deno project per database BuildDir = ".build" // bundles and their manifest, written by `backd functions build` ManifestFile = "manifest.json" FunctionFile = "function.yaml" InputSchemaFile = "input.schema.json" OutputSchemaFile = "output.schema.json" )
Function layout inside a database directory.
const ( ModeSync = "sync" ModeAsync = "async" ModeWebhook = "webhook" )
Function modes.
const ( DefaultSyncTimeout = 10 * time.Second DefaultAsyncTimeout = 15 * time.Minute MaxSyncTimeout = 60 * time.Second MaxAsyncTimeout = 24 * time.Hour DefaultMemory = 128 << 20 DefaultMaxOutput = 1 << 20 MaxSyncOutput = 64 << 20 // MaxAsyncOutput keeps an async job's result within one MongoDB // document (16 MiB, minus room for the job's other fields). MaxAsyncOutput = 15 << 20 DefaultConcurrency = 10 )
Defaults and bounds of function.yaml values.
const ( SignupOpen = "open" SignupInvite = "invite" SignupClosed = "closed" )
Signup modes.
const ( DefaultIdleTimeout = 30 * 24 * time.Hour DefaultMaxLifetime = 90 * 24 * time.Hour DefaultAuditRetention = 365 * 24 * time.Hour // DefaultLogRetention is functions.log_retention's default: a short // debugging window, not a log archive (see the docs). DefaultLogRetention = 7 * 24 * time.Hour // DefaultJobRetention is functions.job_retention's default: how long // an async job's result is kept once done (roadmap F11). DefaultJobRetention = 24 * time.Hour DefaultPasswordMinLength = 12 )
Defaults for realm settings left out of realm.yaml.
const ( DefaultEmailPerKindPerHour = 3 DefaultEmailPerDay = 10 DefaultEmailPerIPPerHour = 20 // The caps of custom emails from functions. DefaultEmailPerFunctionPerHour = 200 DefaultEmailPerInvocation = 50 DefaultEmailRecipientsPerMessage = 10 // DefaultLocale is email.default_locale when not set. DefaultLocale = "en" )
Defaults of email.limits.
const CollectionFile = "collection.yaml"
CollectionFile is the optional file next to a collection's schema.json holding its data policy for an erased user.
const DefaultRedirectDelay = 3 * time.Second
DefaultRedirectDelay is email.redirect_delay when not set.
const DefaultResetPasswordTTL = time.Hour
DefaultResetPasswordTTL is account.tokens.reset_password when not set.
const DefaultVerifyEmailTTL = 48 * time.Hour
DefaultVerifyEmailTTL is account.tokens.verify_email when not set.
const DenoVersion = "2.9.7"
DenoVersion is the Deno version functions are bundled and run with. `backd functions build` requires exactly this version, and the executor image is built from it.
const MaxCallChain = 4
MaxCallChain is the longest chain of functions calling each other, the entry function included.
const RealmFile = "realm.yaml"
RealmFile is the name of the required realm settings file.
const (
// SchemaFile is the name of a collection's schema file.
SchemaFile = schemaFile
)
const SystemDatabaseSuffix = "___system"
SystemDatabaseSuffix is appended to a realm name to form the MongoDB database holding the realm's users, sessions and keys.
Variables ¶
var ReservedDirs = []string{email.DirName, email.PagesDirName}
ReservedDirs are folders of a realm that hold something other than a database: they are never read as databases.
var SystemFields = []string{"id", "_meta.created_at", "_meta.updated_at", "_meta.version", "_meta.owner", "_meta.created_by", "_meta.updated_by"}
SystemFields are the server-owned fields that can be queried, sorted and indexed in addition to the schema's fields.
Functions ¶
func NormalizeEmail ¶
NormalizeEmail trims and lowercases an email address and checks its basic shape (one "@" with text on both sides, no spaces). The reserved ".invalid" top-level domain (RFC 2606) is refused: it never receives mail, and erased users' placeholder addresses live there, so nobody may take one. Characters that delimit addresses or break a header (commas, angle brackets, quotes, control characters...) are refused as well: a delivery function that joins recipients with commas must never see one address that is really two.
func ParseDuration ¶
ParseDuration parses a Go duration ("12h", "90m") or a whole number of days ("30d").
func SourceHash ¶
SourceHash hashes every file of a functions project, except hidden entries (such as .build), so any change to code, shared lib/, deno.json, deno.lock or schemas changes it.
func ValidSecretName ¶
ValidSecretName reports whether name is a valid secret NAME (upper-case letters, digits and _, starting with a letter) — the same rule function.yaml's secrets list is checked against, without the leading "realm." a reference may carry.
Types ¶
type AccountSettings ¶ added in v0.4.0
type AccountSettings struct {
// RequireVerifiedEmail: no session until the address is verified.
RequireVerifiedEmail bool
// WelcomeEmail sends the welcome email once the address is verified.
WelcomeEmail bool
// VerifyEmailTTL is how long a verification link works (account.tokens.verify_email).
VerifyEmailTTL time.Duration
// AllowEmailChange lets users change their own address (`POST /_auth/email`).
AllowEmailChange bool
// ChangeEmailTTL and RevertEmailChangeTTL are how long the confirmation
// and the undo link of an email change work.
ChangeEmailTTL, RevertEmailChangeTTL time.Duration
// ResetPasswordTTL is how long a reset link works (account.tokens.reset_password).
ResetPasswordTTL time.Duration
// PurgeUnverifiedAfter deletes accounts that never verified; 0 is off.
PurgeUnverifiedAfter time.Duration
}
AccountSettings are the account lifecycle settings of a realm.
func (AccountSettings) TokenLifetime ¶ added in v0.4.0
func (a AccountSettings) TokenLifetime(p email.Purpose) time.Duration
TokenLifetime is how long a token of this purpose works in the realm.
type Collection ¶
type Collection struct {
Realm string
Database string
MongoDatabase string // <realm>__<database>
Name string
SchemaPath string // path of schema.json, for error messages
RawSchema map[string]any // decoded schema.json (numbers as json.Number)
Schema *jsonschema.Schema // compiled draft 2020-12 schema
Fields map[string]Field // dot path → field info, for query checks
Indexes []Index // declared in indexes.json
IndexPath string // path of indexes.json, when present
Rules *rules.Set // from rules.yaml; nil allows nothing
Erasure *ErasurePolicy // from collection.yaml; nil: an erase leaves the collection alone
ErasurePath string // path of collection.yaml, for error messages
}
Collection is a set of documents validated by one JSON Schema.
func (*Collection) ArrayField ¶
func (c *Collection) ArrayField(path string) bool
ArrayField reports whether path is declared as an array (only), with no array on the way to it.
func (*Collection) IsKnownField ¶
func (c *Collection) IsKnownField(path string) bool
IsKnownField reports whether path is a system field or declared in the schema.
func (*Collection) ScalarField ¶
func (c *Collection) ScalarField(path string) bool
ScalarField reports whether path holds a single value: a system field, or a declared field whose types exclude "array", with no array on the way to it.
type Database ¶
type Database struct {
Realm string
Name string
MongoName string // <realm>__<database>
Collections map[string]*Collection
Functions *Functions // from _functions/; nil when the database has none
}
Database is one application's data, stored in one MongoDB database.
func (*Database) SortedCollections ¶
func (d *Database) SortedCollections() []*Collection
SortedCollections returns the database's collections sorted by name.
type EmailLimits ¶ added in v0.4.0
type EmailLimits struct {
PerKindPerHour int // emails of one kind to one recipient, per hour
PerDay int // emails to one recipient, per day
PerIPPerHour int // email-sending requests from one client address, per hour
// The caps of custom emails from functions (ctx.email.send), whoever the
// recipients are.
PerFunctionPerHour int // messages one function sends, per hour
PerInvocation int // messages one invocation sends
RecipientsPerMessage int // to, cc and bcc of one message
}
EmailLimits bound how many emails one address, and one client address, can cause.
type EmailSettings ¶ added in v0.4.0
type EmailSettings struct {
Function string // <database>/<function>: internal and async
From string // "Name <address>" or an address
ReplyTo string // optional
PublicURL string // overrides BACKD_URL for this realm's links; no trailing slash
DefaultLocale string
Locales []string // every one needs every required template
Limits EmailLimits
// RedirectDelay is how long a hosted result page waits before it sends the
// user on (email.redirect_delay).
RedirectDelay time.Duration
// Redirects are where the hosted pages send users afterwards, by flow
// (verify_email, reset_password, change_email, invitation), when the
// request that caused the email named no other place.
Redirects map[string]string
// AllowedRedirects are the origins (https://app.example.com) and app
// schemes (acme://) that redirect_to, redirects and links may point at.
AllowedRedirects []string
// Links replace the hosted page of a flow with a page of the app: the
// link in the email is this URL, with {token} replaced.
Links map[string]string
// Timeout is the delivery function's own timeout, set when the config is
// loaded; email jobs lease for it.
Timeout time.Duration
}
EmailSettings are the email settings of a realm: which function delivers its messages and who they come from. backd renders the messages and never sends one itself.
func (EmailSettings) AllowedRedirect ¶ added in v0.4.0
func (e EmailSettings) AllowedRedirect(raw string) bool
AllowedRedirect reports whether raw is an absolute URL on one of the allowed origins or app schemes: where a page may send a user.
func (EmailSettings) DatabaseAndName ¶ added in v0.4.0
func (e EmailSettings) DatabaseAndName() (string, string)
DatabaseAndName splits Function into the database and the function name.
type ErasurePolicy ¶ added in v0.4.0
type ErasurePolicy struct {
// Action applies to the documents whose _meta.owner is the user: "" leaves
// them, ErasureDelete removes them, ErasureAnonymize applies Remove and
// Replace and clears the owner.
Action string
Remove []string // fields removed (anonymize)
Replace map[string]any // fields set to a fixed value (anonymize)
// Pull and Unset act on every document of the collection, whoever owns it:
// the user is removed from the array field / cleared from the field. The
// value says what the field holds: MatchEmail or MatchID.
Pull map[string]string
Unset map[string]string
}
ErasurePolicy is what an erase does to a collection (collection.yaml's on_owner_delete). A collection without the file is left alone.
func (*ErasurePolicy) Fields ¶ added in v0.4.0
func (p *ErasurePolicy) Fields() []string
Fields lists every field the policy touches, for the indexes it needs.
func (*ErasurePolicy) IndexedFields ¶ added in v0.4.0
func (p *ErasurePolicy) IndexedFields() []string
IndexedFields are the fields an erase searches by: the arrays and fields that hold the user (pull and unset), which need an index to be found without scanning the collection.
type Field ¶
type Field struct {
Types []string // JSON Schema types; empty when the schema doesn't constrain it
ItemTypes []string // for arrays: the types of the items, when declared
}
Field describes one property path declared in a collection schema.
type Function ¶
type Function struct {
Realm, Database, Name string
Dir string // the function's folder
Entry string // index.js or index.ts, relative to the project (slash-separated)
Mode string
Timeout time.Duration
Memory int64 // bytes
MaxOutput int64 // bytes
Concurrency int
RateLimit *RateLimit // nil: none
Retry *Retry // nil: a single attempt
Idempotency string // optional or required
Invoke *rules.Rule // nil: only API keys may invoke
Admin bool // ctx.admin.db with full access
Internal bool // no HTTP route: only backd, scheduled runs and other functions call it
Email bool // ctx.email.send: may send custom emails through the realm's templates and delivery function
DevOnly bool // backd refuses to start with it unless BACKD_DEV=true (development helpers)
Calls []string // functions of the same database this one may ctx.call
Schedule *cron.Schedule // nil: not scheduled
ScheduleExpr string
Secrets []SecretRef
Network []string // hosts (host or host:port) the function may reach
InputSchema *jsonschema.Schema
OutputSchema *jsonschema.Schema
}
Function is one function, from its folder in _functions/.
type Functions ¶
type Functions struct {
Dir string // the _functions directory
Functions map[string]*Function // by name
}
Functions is a database's Deno project of functions (`_functions/`).
type Manifest ¶
type Manifest struct {
Deno string `json:"deno"`
Source string `json:"source"` // SourceHash of the project when built
Functions map[string]ManifestBundle `json:"functions"`
}
Manifest describes the bundles `backd functions build` wrote for one functions project.
func ReadManifest ¶
ReadManifest reads a project's .build/manifest.json.
type ManifestBundle ¶
type ManifestBundle struct {
Bundle string `json:"bundle"` // file name in .build
SHA256 string `json:"sha256"`
}
ManifestBundle is one function's bundle.
type Networks ¶
Networks is a list of IP networks. An empty list restricts nothing.
func ParseNetworks ¶
ParseNetworks parses IP addresses and CIDR networks, IPv4 or IPv6.
func (Networks) Allows ¶
Allows reports whether addr is in one of the networks; an empty list allows every address. addr is an IP address such as the one the HTTP layer resolves with TRUSTED_PROXIES; an unparsable one is refused by a non-empty list.
type Realm ¶
type Realm struct {
Name string
Settings RealmSettings // from realm.yaml
Databases map[string]*Database
// Email holds the parsed email templates of <realm>/email/; nil when the
// realm doesn't configure email.
Email *email.Templates
// Pages are the hosted pages the links in emails open (<realm>/pages/);
// nil when the realm doesn't configure email.
Pages *email.Pages
}
Realm groups databases and owns a user pool.
type RealmSettings ¶
type RealmSettings struct {
AuthEnabled bool
Signup string
IdleTimeout time.Duration
MaxLifetime time.Duration
PasswordMinLength int
CORSOrigins []string
Roles map[string]Role
// AdminNetworks restricts every admin API request (admin.allowed_networks);
// empty means unrestricted.
AdminNetworks Networks
// UserNetworks are the network restrictions realm.yaml sets per user
// email (in a role's user entries).
UserNetworks map[string]UserNetworks
// AuditRetention is how long audit records are kept (audit.retention);
// DefaultAuditRetention when not set.
AuditRetention time.Duration
// FunctionsMaxConcurrency caps how many function calls may run at once
// on this backd instance (functions.max_concurrency); 0 means
// unlimited. Applies whether or not auth is enabled.
FunctionsMaxConcurrency int
// FunctionsLogRetention is how long invocation records (roadmap F10)
// are kept (functions.log_retention); DefaultLogRetention when not
// set. Needs auth enabled, like the rest of functions.* except
// max_concurrency: there's no system database to store them in
// otherwise.
FunctionsLogRetention time.Duration
// FunctionsJobRetention is how long an async job's result (roadmap
// F11) is kept once done (functions.job_retention); DefaultJobRetention
// when not set. Needs auth enabled, like FunctionsLogRetention.
FunctionsJobRetention time.Duration
// Email is how the realm sends email (email in realm.yaml); nil when it
// doesn't, and then no email is ever sent.
Email *EmailSettings
// Account is how the realm's accounts behave (account in realm.yaml).
Account AccountSettings
}
RealmSettings are the realm-level settings from realm.yaml, with defaults applied.
func (RealmSettings) AdminRoles ¶
func (s RealmSettings) AdminRoles() []string
AdminRoles returns the names of the roles declared with admin: true, sorted.
func (RealmSettings) BestLocale ¶ added in v0.4.0
func (s RealmSettings) BestLocale(tags ...string) string
BestLocale maps the languages a person asked for, most wanted first, to the best language the realm lists, without ever failing: an exact match (es-MX), then the same language with its region dropped (es), then the default. The first tag that matches either way wins, so ["fr-CA", "es"] on a realm that lists es and en gives es.
func (RealmSettings) IsAdmin ¶
func (s RealmSettings) IsAdmin(roles []string) bool
IsAdmin reports whether roles include an admin role of the realm.
func (RealmSettings) Languages ¶ added in v0.4.0
func (s RealmSettings) Languages() (def string, list []string)
Languages returns a realm's default language and the languages it supports: email.default_locale and email.locales, or just English when it configures no email.
func (RealmSettings) ListedLocale ¶ added in v0.4.0
func (s RealmSettings) ListedLocale(tag string) string
ListedLocale returns the listed language equal to tag, ignoring case (es-mx finds es-MX), or "" when the realm doesn't list it.
type Registry ¶
Registry is the loaded configuration. It is read-only after Load.
func Load ¶
Load walks root and builds the registry. Every problem found is reported, each naming the offending path.
func (*Registry) AuthRealms ¶ added in v0.4.0
AuthRealms returns the realms with auth enabled (the ones with users, and so with jobs), sorted.
func (*Registry) CheckBundles ¶
CheckBundles reports functions projects whose bundles are missing, were built by another Deno version, don't match the sources, or were changed since the build. Startup refuses to run with any of them.
func (*Registry) Collection ¶
func (r *Registry) Collection(realm, database, collection string) (*Collection, bool)
Collection returns the collection at realm/database/collection, if configured.
func (*Registry) Fingerprint ¶
Fingerprint identifies the config: a SHA-256 over every file backd reads from CONFIG_DIR — realm.yaml, each collection's schema.json, indexes.json and rules.yaml, and each functions project with its bundles — by relative path, length and content. Files backd ignores (hidden entries such as .git, stray files) don't change it, so the same checkout always has the same fingerprint, on any machine.
func (*Registry) FunctionRealms ¶
FunctionRealms returns the realms with at least one function, sorted.
func (*Registry) RealmNames ¶
RealmNames returns every configured realm's name, sorted.
func (*Registry) SortedRealms ¶
SortedRealms returns every realm, sorted by name.
type Retry ¶ added in v0.4.0
type Retry struct {
Attempts int // total attempts, the first included
Backoff time.Duration // the wait after the first failure; doubles after each one
MaxBackoff time.Duration // the longest single wait
}
Retry is an async function's retry policy: how often a failed attempt is repeated and how long to wait between attempts.
type Role ¶
type Role struct {
Description string
// Admin roles let the sessions of users holding them use the admin API.
Admin bool
// Users are seed assignments: normalized (trimmed, lowercased) emails.
Users []string
}
Role is a role declared in realm.yaml.
type SecretRef ¶
SecretRef names a secret a function may read: its own database's (`NAME`) or the realm's (`realm.NAME`).
type UserNetworks ¶
type UserNetworks struct {
Admin Networks // the user's admin API requests; within AdminNetworks
Login Networks // login and every request with the user's session
}
UserNetworks restricts where one user may act from.