Documentation
¶
Overview ¶
Package flexitype is the embedding facade: everything needed to run flexitype inside your own Go service — usecases, storage, migrations, domain events — wired through one constructor with hook options for your pub/sub, webhooks or plain functions. For the standalone service, see cmd/flexitype.
Index ¶
- type APIConfig
- type DeliveryLoops
- type Option
- func WithBackgroundErrorObserver(fn func(err error)) Option
- func WithBlobStore(s blob.Store) Option
- func WithCleanupObserver(fn func(err error)) Option
- func WithDeadLetterRetention(d time.Duration) Option
- func WithDeliveryWorker(opts ...webhook.WorkerOption) Option
- func WithDispatchObserver(fn func(ctx context.Context, err error)) Option
- func WithEventRetention(d time.Duration) Option
- func WithFailClosedACL() Option
- func WithGraphQLFederation() Option
- func WithHandler(h events.Handler, opts ...events.RegisterOption) Option
- func WithHandlerFunc(name string, fn func(ctx context.Context, env events.Envelope) error, ...) Option
- func WithOutbox(opts ...outbox.RelayOption) Option
- func WithPublisher(name string, pub events.Publisher, topicFn events.TopicFunc) Option
- func WithRollbackObserver(fn func(ctx context.Context, err error)) Option
- func WithSearchIndex() Option
- func WithTimeZone(loc *time.Location) Option
- func WithWebhook(name string, cfg events.WebhookConfig, opts ...events.RegisterOption) Option
- func WithWebhookAllowPrivate() Option
- func WithWebhookTimeout(d time.Duration) Option
- func WithoutActivityLog() Option
- func WithoutSearch() Option
- type Service
- func (s *Service) APIHandler(cfg APIConfig) http.Handler
- func (s *Service) AdminInteractor(opts ...admin.Option) *admin.Interactor
- func (s *Service) BootstrapAdmin(ctx context.Context, tenantName, accountName string) (string, error)
- func (s *Service) Context(ctx context.Context) context.Context
- func (s *Service) Dispatcher() *events.Dispatcher
- func (s *Service) EnsureWebhookSubscription(ctx context.Context, name, url, secret string, eventTypes ...string) error
- func (s *Service) Factory() application.Factory
- func (s *Service) GraphQLEngine() *gql.Engine
- func (s *Service) Interactors(ctx context.Context) *application.Interactors
- func (s *Service) Migrate(ctx context.Context) error
- func (s *Service) NewAPIHandler(cfg APIConfig) (http.Handler, error)
- func (s *Service) NewAccountLookup(ttl time.Duration) serviceaccount.Authenticator
- func (s *Service) RecomputeComputed(ctx context.Context, tenant valueobjects.TenantID) (int, error)
- func (s *Service) ReindexSearch(ctx context.Context, tenant valueobjects.TenantID) (int, error)
- func (s *Service) RunChangeSetScheduler(ctx context.Context, interval time.Duration)
- func (s *Service) RunOutboxRelay(ctx context.Context, loops ...DeliveryLoops)
- func (s *Service) SchemaDrift(ctx context.Context) ([]int, error)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type APIConfig ¶
type APIConfig struct {
Logger *logger.Logger
Health *health.Service
// Accounts authenticates bearer tokens.
//
// NIL SERVES THE ENTIRE API TO UNAUTHENTICATED CALLERS, including the
// irreversible POST /admin/purge. It is a development convenience and
// nothing else, so it must be opted into by name with AllowAnonymous.
// Without that, APIHandler panics and NewAPIHandler returns an error —
// mirroring the standalone binary, which refuses to boot in this state.
Accounts serviceaccount.Authenticator
// AllowAnonymous opts a deployment into serving the whole API without
// authentication. It exists so that state cannot be reached by omission.
//
// The standalone binary has FLEXITYPE_DEV_INSECURE for the same purpose.
// Library mode had no equivalent: the fail-closed default was added to
// internal/config, which only governs the binary, so an embedder who read
// the release note about authentication becoming fail-closed would
// reasonably have assumed it applied to them.
AllowAnonymous bool
// Metrics, when set, records HTTP SLIs and serves /metrics. With the
// outbox on, delivery-depth gauges are registered automatically.
Metrics *metrics.Metrics
// EnableProvisioning turns on the admin-scoped tenant/service-account
// API (database-backed only).
EnableProvisioning bool
// RateLimiter, when set, throttles API requests per service account
// (429 + Retry-After). Build one with ratelimit.New.
RateLimiter *ratelimit.Limiter
// TenantRateLimiter, when set, caps a tenant's aggregate request rate
// across all of its service accounts.
TenantRateLimiter *ratelimit.Limiter
// AuthRateLimiter, when set, throttles by client address BEFORE
// authentication. The other two limiters key on a resolved principal, so
// neither can throttle a FAILED authentication — and each of those costs
// a database round trip and a hash, uncached, so an unauthenticated
// caller could exhaust the pool and brute-force tokens unthrottled.
//
// Behind a proxy this keys on the proxy, giving a ceiling on aggregate
// unauthenticated traffic rather than a per-client one. It deliberately
// does not read X-Forwarded-For: a header is attacker-supplied, so
// trusting it would let one client spread its attempts across unlimited
// keys.
AuthRateLimiter *ratelimit.Limiter
// DisableConsole omits the admin-console SPA, for an API-only deployment.
// An unmatched path then returns a JSON 404 like any other API error.
DisableConsole bool
// MaxImportBytes caps a CSV import upload; 0 uses the 16 MiB default.
// GET /features reports the effective value, so a client can chunk a
// bulk load against the real ceiling instead of guessing.
MaxImportBytes int64
// MaxMediaBytes caps a media upload; 0 uses the 32 MiB default.
MaxMediaBytes int64
}
APIConfig configures the mountable REST API for embedded deployments.
type DeliveryLoops ¶ added in v1.3.0
type DeliveryLoops struct {
// Relay expands the outbox and dispatches to in-process hooks.
Relay bool
// Worker delivers webhook subscriptions.
Worker bool
// Pruner enforces event retention.
Pruner bool
}
DeliveryLoops selects which delivery loops a process runs, so an API tier and a worker tier can be scaled, autoscaled and drained separately from one image.
No leader election is involved: every loop claims work with a lease and FOR UPDATE SKIP LOCKED, so running one on any number of replicas is safe. The switches exist because ten API replicas polling the outbox every two seconds is load that a scaling decision made for request traffic should not create.
func AllDeliveryLoops ¶ added in v1.3.0
func AllDeliveryLoops() DeliveryLoops
AllDeliveryLoops runs everything — the single-process default.
type Option ¶
type Option func(*options)
Option customises an embedded Service.
func WithBackgroundErrorObserver ¶
WithBackgroundErrorObserver observes errors from the background schedulers (the change-set publisher and the events-feed pruner), which would otherwise be dropped silently. Use it to log or meter them.
func WithBlobStore ¶
WithBlobStore backs media attribute values with an object store (local disk, S3-compatible, …). Without it, media uploads return a validation error.
func WithCleanupObserver ¶ added in v1.1.0
WithCleanupObserver observes swallowed post-erasure cleanup failures — a media-blob GC or search-projection removal that could not be completed after a committed erasure. These are best-effort by design (they must not undo a durable erasure), so use this to log or meter them rather than lose them. Media-blob failures are additionally reported in PurgeReport.MediaBlobsFailed / UnpurgedBlobKeys.
func WithDeadLetterRetention ¶ added in v1.3.0
WithDeadLetterRetention bounds how long a DEAD delivery is kept (default 30 days). Only meaningful with WithOutbox.
The envelope prune keeps anything a dead delivery references, which is what makes a dead letter redrivable — but nothing else deleted a dead row, so one decommissioned endpoint pinned its envelopes for ever and the event retention stopped bounding the outbox or the feed at all. This is where that bound lives. It is far longer than the event retention on purpose: a dead letter has to outlive the events it references long enough for an operator to notice it.
func WithDeliveryWorker ¶
func WithDeliveryWorker(opts ...webhook.WorkerOption) Option
WithDeliveryWorker customises the webhook delivery worker (attempt cap, concurrency, HTTP client). Only meaningful with WithOutbox.
func WithDispatchObserver ¶
WithDispatchObserver observes synchronous post-commit event-dispatch failures. In the default (non-outbox) mode the write is already durable when subscribers run, so a subscriber error is reported here instead of failing the request. Use WithOutbox for at-least-once delivery guarantees.
func WithEventRetention ¶
WithEventRetention sets how long expanded events stay readable in the feed before pruning (default 7 days). Only meaningful with WithOutbox.
func WithFailClosedACL ¶ added in v1.3.0
func WithFailClosedACL() Option
WithFailClosedACL inverts the field-ACL default: a context that carries no uow.Access policy denies every attribute instead of granting admin.
The standalone service always stamps a policy from the authenticated service account, so this option is for embedders. In library mode the host is responsible for stamping the policy on every request, and nothing otherwise enforces that it did — a background job or a new resolver that forgets silently runs with full field access. With this option it fails instead.
Stamp uow.WithAccess on every request path, and uow.WithSystemAccess on host-owned background work that legitimately has no principal. The setting applies to the whole process and cannot be undone; see uow.RequireAccessPolicy.
func WithGraphQLFederation ¶ added in v1.3.0
func WithGraphQLFederation() Option
WithGraphQLFederation exposes the GraphQL endpoint as an Apollo-Federation subgraph: `_service { sdl }`, `_entities(representations:)`, and `@key(fields: "entityId")` on every entity type.
Without it the endpoint is a standalone schema that a federated gateway cannot compose at all. With it, a gateway resolves an entity this service holds attributes for from the entity id another subgraph already owns, which is the natural modelling for an attribute service.
It is off by default: a federated schema carries three fields no standalone client asks for, and `_entities` is a batch read a non-federated deployment has no reason to expose.
func WithHandler ¶
func WithHandler(h events.Handler, opts ...events.RegisterOption) Option
WithHandler registers a dispatcher hook: any events.Handler your infrastructure provides.
func WithHandlerFunc ¶
func WithHandlerFunc(name string, fn func(ctx context.Context, env events.Envelope) error, opts ...events.RegisterOption) Option
WithHandlerFunc registers a plain function hook.
func WithOutbox ¶
func WithOutbox(opts ...outbox.RelayOption) Option
WithOutbox upgrades event delivery to at-least-once: envelopes persist in the same transaction as the change and a relay dispatches them with retries. It also unlocks the standalone-consumer surface — webhook subscriptions and the events feed. Run the delivery machinery with Service.RunOutboxRelay.
func WithPublisher ¶
WithPublisher routes events into your pub/sub broker (NATS, Kafka, SNS, ...). topicFn may be nil to use the event type as the topic.
func WithRollbackObserver ¶
WithRollbackObserver observes rolled-back units of work.
func WithSearchIndex ¶
func WithSearchIndex() Option
WithSearchIndex enables the entity search projection: an internal-projection subscriber keeps one searchable document per entity, unlocking FQL matches(). The index is maintained synchronously in the writing request (read-your-writes) in both delivery modes, so it stays fresh independent of WithOutbox (#211).
func WithTimeZone ¶ added in v1.3.0
WithTimeZone sets the calendar day that `today` and `now` resolve against in dependency conditions and dynamic defaults. Default UTC.
It changes which day those name, not how anything is stored: a date value is a calendar date held as midnight UTC either way. Without it, a tenant operating outside UTC had a date-boundary rule that was wrong for part of every day — a condition on "expires before today" flipped at the wrong hour, and a `today` default recorded yesterday for anything created after the UTC midnight.
Per-request override: stamp uow.WithTimeZone on the context, which is how an embedder serves tenants in different zones from one process.
func WithWebhook ¶
func WithWebhook(name string, cfg events.WebhookConfig, opts ...events.RegisterOption) Option
WithWebhook delivers events as signed JSON POSTs to a receiving endpoint.
func WithWebhookAllowPrivate ¶
func WithWebhookAllowPrivate() Option
WithWebhookAllowPrivate lets webhook subscriptions target private, loopback and link-local hosts over http — for on-prem deployments whose consumers live on internal networks. Off by default (SSRF guard).
func WithWebhookTimeout ¶ added in v1.3.0
WithWebhookTimeout bounds one webhook delivery attempt (default 10s).
It is a duration rather than an *http.Client on purpose: the delivery client is the SSRF guard, and supplying a client would replace that guard without saying so.
func WithoutActivityLog ¶
func WithoutActivityLog() Option
WithoutActivityLog disables the audit log entirely: no pre-commit writes, no read API.
func WithoutSearch ¶
func WithoutSearch() Option
WithoutSearch disables the FQL query surface for this deployment.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service is an embedded flexitype instance.
func New ¶
New wires an embedded flexitype over your connection pool. The pool is shared, never owned: closing it remains your call.
func NewInMemory ¶
NewInMemory wires flexitype over the in-memory store: no database, no migrations. Same usecases, same API, same hooks — it powers the browser playground and makes a zero-dependency test double for embedding consumers. Data lives for the process only; WithOutbox is ignored (direct dispatch is already synchronous and in-process).
func (*Service) APIHandler ¶
APIHandler returns flexitype's versioned REST API as an http.Handler you can mount in your own router.
It PANICS when the configuration would serve the API to unauthenticated callers without an explicit opt-in — that is a composition-time misconfiguration, so it fails at startup rather than per request. Use NewAPIHandler to handle it as an error instead.
func (*Service) AdminInteractor ¶
func (s *Service) AdminInteractor(opts ...admin.Option) *admin.Interactor
AdminInteractor returns the provisioning usecases over this service's pool, or nil for in-memory services.
opts are passed through; APIHandler wires admin.WithAuthCache when the deployment authenticates through a caching authenticator, so a rotation or a revocation takes effect at once rather than at the end of the cache TTL.
func (*Service) BootstrapAdmin ¶
func (s *Service) BootstrapAdmin(ctx context.Context, tenantName, accountName string) (string, error)
BootstrapAdmin seeds the provisioning tables with a tenant and an admin-scoped service account when no accounts exist yet, returning the one-time token so an operator can call the admin API. It is idempotent: once any account exists it returns an empty token and does nothing. This is the only way to get the first credential into a database-backed deployment.
func (*Service) Context ¶ added in v1.3.0
Context returns ctx with the service-wide defaults stamped on it: the deployment's time zone, when one is configured.
It exists because those defaults have to travel on the context the CALLER passes to each interactor method. Stamping them inside Interactors derived a context that was then discarded, so FLEXITYPE_TIMEZONE never reached rule evaluation and every `today`/`now` dependency rule and dynamic default resolved in UTC — the read and write paths agreeing only because both were wrong. The API stamps the same defaults in its middleware, which owns the request context.
A caller that already chose a zone keeps it, which is how a host serves tenants in different zones from one process.
func (*Service) Dispatcher ¶
func (s *Service) Dispatcher() *events.Dispatcher
Dispatcher exposes the event dispatcher, for inspection and for registering hooks.
Late registration is safe: the dispatcher copies its handler slice on write under an RWMutex, so a Register concurrent with a Dispatch cannot race. (This comment previously said the opposite, and had done since before the copy-on-write change.)
func (*Service) EnsureWebhookSubscription ¶
func (s *Service) EnsureWebhookSubscription(ctx context.Context, name, url, secret string, eventTypes ...string) error
EnsureWebhookSubscription upserts a webhook subscription by name — the bootstrap path for environment-configured endpoints. Errors unless WithOutbox is enabled.
func (*Service) Factory ¶
func (s *Service) Factory() application.Factory
Factory exposes the underlying usecase factory for advanced wiring.
func (*Service) GraphQLEngine ¶
GraphQLEngine exposes the read-only GraphQL engine, for embedders that build their own API handler (e.g. the WASM playground).
func (*Service) Interactors ¶
func (s *Service) Interactors(ctx context.Context) *application.Interactors
Interactors returns a request-scoped usecase set. Call once per request or unit of work so dataloader caches stay request-local.
PASS THE CONTEXT THROUGH Context FIRST when the deployment sets a time zone. An interactor set carries no context of its own — every method takes one from its caller — so a zone stamped here would reach nothing:
ctx = svc.Context(ctx) it := svc.Interactors(ctx) schema, err := it.TypeDefinitions().EffectiveAttributes(ctx, typeID)
func (*Service) Migrate ¶
Migrate applies flexitype's embedded schema migrations. Safe to call on every startup; concurrent callers serialize on an advisory lock. No-op for in-memory services.
func (*Service) NewAPIHandler ¶ added in v1.3.0
NewAPIHandler is APIHandler with the configuration check reported as an error rather than a panic.
func (*Service) NewAccountLookup ¶
func (s *Service) NewAccountLookup(ttl time.Duration) serviceaccount.Authenticator
NewAccountLookup returns a database-backed authenticator over this service's pool, with a short success cache so revocation propagates within ttl. nil for in-memory services.
func (*Service) RecomputeComputed ¶ added in v1.1.0
RecomputeComputed re-materializes every entity's computed attributes for a tenant — the recovery counterpart to ReindexSearch. Internal projections are maintained in the originating request's post-commit (issue #211), so a process crash between commit and that post-commit can leave a computed value stale; this rebuilds them all. Returns the number of entities recomputed.
func (*Service) ReindexSearch ¶
ReindexSearch rebuilds every entity search document for a tenant. Errors unless WithSearchIndex is enabled.
func (*Service) RunChangeSetScheduler ¶
RunChangeSetScheduler publishes approved change-sets whose publish_at has arrived, on the given interval, until ctx ends. Run it as a goroutine next to the server; every replica runs it safely (a published set is skipped by the others). A zero interval defaults to one minute.
func (*Service) RunOutboxRelay ¶
func (s *Service) RunOutboxRelay(ctx context.Context, loops ...DeliveryLoops)
RunOutboxRelay runs the event-delivery machinery until ctx ends: the outbox relay (expansion + in-process dispatch), the webhook delivery worker and the retention pruner. No-op without WithOutbox. Run it as a goroutine next to the server; every replica runs it safely.
func (*Service) SchemaDrift ¶ added in v1.3.0
SchemaDrift reports migration versions the database has applied that this binary does not carry — the schema is newer than this build.
A rolling deploy makes that state normal for a while: the first new pod migrates while the previous generation keeps serving. flexitype supports it (each release's migrations stay compatible with the previous binary, see docs/upgrades.md), but an operator should be able to see a mixed-version fleet rather than infer it. It returns nothing for an in-memory service and nothing when the schema matches.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package api embeds and serves the OpenAPI 3 description of the flexitype REST API.
|
Package api embeds and serves the OpenAPI 3 description of the flexitype REST API. |
|
Package application wires flexitype's usecases behind a request-scoped factory.
|
Package application wires flexitype's usecases behind a request-scoped factory. |
|
activity
Package activity defines the change-audit vocabulary: usecases record Changes with before/after snapshots; the unit of work's pre-commit handler serializes them into activity-log entries written in the same transaction as the change itself.
|
Package activity defines the change-audit vocabulary: usecases record Changes with before/after snapshots; the unit of work's pre-commit handler serializes them into activity-log entries written in the same transaction as the change itself. |
|
admin
Package admin implements runtime provisioning of tenants and service accounts — the hosted-tier control plane.
|
Package admin implements runtime provisioning of tenants and service accounts — the hosted-tier control plane. |
|
appctx
Package appctx holds the request-scoped vocabulary shared between the composition root and the feature subpackages (search, gql, computed): the per-request Repositories set and the ports handed around with it.
|
Package appctx holds the request-scoped vocabulary shared between the composition root and the feature subpackages (search, gql, computed): the per-request Repositories set and the ports handed around with it. |
|
attribute
Package attribute holds the attribute-definition usecases.
|
Package attribute holds the attribute-definition usecases. |
|
changeset
Package changeset batches value mutations into a reviewable draft that leaves live data untouched until it is published.
|
Package changeset batches value mutations into a reviewable draft that leaves live data untouched until it is published. |
|
computed
Package computed materializes read-only computed attributes.
|
Package computed materializes read-only computed attributes. |
|
dedup
Package dedup finds probable duplicate entities: an operator declares matching rules (an attribute plus a comparison strategy) per type, and a scan reports candidate pairs with similarity scores.
|
Package dedup finds probable duplicate entities: an operator declares matching rules (an attribute plus a comparison strategy) per type, and a scan reports candidate pairs with similarity scores. |
|
dependency
Package dependency holds the attribute-dependency usecases, including effective-schema resolution for building cascading UIs.
|
Package dependency holds the attribute-dependency usecases, including effective-schema resolution for building cascading UIs. |
|
erasure
Package erasure owns the right-to-erasure orchestration: the irreversible, audited hard delete of an entity's or a tenant's data across attribute values, revisions, relationships, the search projection and media blobs.
|
Package erasure owns the right-to-erasure orchestration: the irreversible, audited hard delete of an entity's or a tenant's data across attribute values, revisions, relationships, the search projection and media blobs. |
|
feed
Package feed serves the ordered event log to pull consumers: cursor pages over expanded envelopes, an SSE-friendly tail, and named compare-and-swap cursors so a replicated consuming service reads as one logical consumer.
|
Package feed serves the ordered event log to pull consumers: cursor pages over expanded envelopes, an SSE-friendly tail, and named compare-and-swap cursors so a replicated consuming service reads as one logical consumer. |
|
fieldacl
Package fieldacl applies the per-attribute access policy to every surface that returns or accepts attribute values.
|
Package fieldacl applies the per-attribute access policy to every surface that returns or accepts attribute values. |
|
gql
Package gql serves a read-only GraphQL API whose schema mirrors a tenant's live type definitions: each entity type becomes an object, each attribute a field, and each relationship a nested Relay connection resolved through the batched repositories (no N+1).
|
Package gql serves a read-only GraphQL API whose schema mirrors a tenant's live type definitions: each entity type becomes an object, each attribute a field, and each relationship a nested Relay connection resolved through the batched repositories (no N+1). |
|
outbox
Package outbox implements at-least-once EXTERNAL event delivery: the unit of work writes envelopes into an outbox table in the same transaction as the change, and a relay dispatches them to the registered external hooks, retrying on failure.
|
Package outbox implements at-least-once EXTERNAL event delivery: the unit of work writes envelopes into an outbox table in the same transaction as the change, and a relay dispatches them to the registered external hooks, retrying on failure. |
|
query
Package query executes FQL: it binds parsed queries against the schema (attributes, relationships, type hierarchies) and hands the bound tree to the persistence layer for compilation.
|
Package query executes FQL: it binds parsed queries against the schema (attributes, relationships, type hierarchies) and hands the bound tree to the persistence layer for compilation. |
|
relationship
Package relationship holds the relationship usecases: defining relationship types between entity types (with their own attribute sets and inheritance) and linking entities under them.
|
Package relationship holds the relationship usecases: defining relationship types between entity types (with their own attribute sets and inheritance) and linking entities under them. |
|
revision
Package revision versions the ENTITY, not just the schema: a revision is an immutable snapshot of all of an entity's live attribute values at a point in time.
|
Package revision versions the ENTITY, not just the schema: a revision is an immutable snapshot of all of an entity's live attribute values at a point in time. |
|
savedview
Package savedview implements saved, shareable entity views: a named FQL query over a root type with chosen display columns and sort.
|
Package savedview implements saved, shareable entity views: a named FQL query over a root type with chosen display columns and sort. |
|
schema
Package schema exports and imports a tenant's schema — its type definitions, attribute definitions, relationship definitions and dependencies — as one JSON bundle keyed entirely by internal name (never by ID), so a bundle is portable across instances.
|
Package schema exports and imports a tenant's schema — its type definitions, attribute definitions, relationship definitions and dependencies — as one JSON bundle keyed entirely by internal name (never by ID), so a bundle is portable across instances. |
|
schema/templates
Package templates ships curated starter schema bundles, embedded in the binary, that a tenant can apply in one call to bootstrap a working schema.
|
Package templates ships curated starter schema bundles, embedded in the binary, that a tenant can apply in one call to bootstrap a working schema. |
|
search
Package search maintains the entity search projection: one document per entity, rebuilt whenever the entity's values change.
|
Package search maintains the entity search projection: one document per entity, rebuilt whenever the entity's values change. |
|
typedef
Package typedef holds the type-definition usecases.
|
Package typedef holds the type-definition usecases. |
|
unit
Package unit holds tenant unit families for quantity attributes: a family (mass, length, …) names a base unit and each member unit's conversion factor to it.
|
Package unit holds tenant unit families for quantity attributes: a family (mass, length, …) names a base unit and each member unit's conversion factor to it. |
|
uow
Package uow provides the shared unit-of-work: transaction wrapping with the standard pre/post/rollback commit handlers, plus per-request actor and tenant context.
|
Package uow provides the shared unit-of-work: transaction wrapping with the standard pre/post/rollback commit handlers, plus per-request actor and tenant context. |
|
value
Package value holds the attribute-value usecases, including the Set flow that validates values against the definition, its constraints and every matched attribute dependency before writing.
|
Package value holds the attribute-value usecases, including the Set flow that validates values against the definition, its constraints and every matched attribute dependency before writing. |
|
webhook
Package webhook delivers events to external services over managed subscriptions: consumers register an HTTPS endpoint and receive every matching envelope as a signed POST, retried with exponential backoff and dead-lettered after a cap.
|
Package webhook delivers events to external services over managed subscriptions: consumers register an HTTPS endpoint and receive every matching envelope as a signed POST, retried with exponential backoff and dead-lettered after a cap. |
|
client
module
|
|
|
cmd
|
|
|
flexitype-wasm
command
The browser playground: the full flexitype service — usecases, REST API, activity log, FQL, search index — compiled to WebAssembly over the in-memory store.
|
The browser playground: the full flexitype service — usecases, REST API, activity log, FQL, search index — compiled to WebAssembly over the in-memory store. |
|
domain
|
|
|
attribute
Package attribute holds the Definition aggregate: a typed, constrained soft attribute attached to a type definition.
|
Package attribute holds the Definition aggregate: a typed, constrained soft attribute attached to a type definition. |
|
dependency
Package dependency holds the AttributeValueDependency aggregate: when a source attribute's value matches all conditions, an effect applies to a target attribute — narrowing its allowed values, adding constraints or overriding whether it is required.
|
Package dependency holds the AttributeValueDependency aggregate: when a source attribute's value matches all conditions, an effect applies to a target attribute — narrowing its allowed values, adding constraints or overriding whether it is required. |
|
errors
Package errors defines flexitype's typed domain errors.
|
Package errors defines flexitype's typed domain errors. |
|
relationship
Package relationship holds the relationship aggregates: Definition (a user-defined relationship type between a parent type and a child type, optionally inheriting from another definition, with its own attributes held by a hidden companion attribute-set type) and Relationship (one link between two entities, optionally pinned to specific type versions).
|
Package relationship holds the relationship aggregates: Definition (a user-defined relationship type between a parent type and a child type, optionally inheriting from another definition, with its own attributes held by a hidden companion attribute-set type) and Relationship (one link between two entities, optionally pinned to specific type versions). |
|
typedef
Package typedef holds the TypeDefinition aggregate: the named "class" of consumer entities (a product, a part, a ticket, ...) that attribute definitions attach to.
|
Package typedef holds the TypeDefinition aggregate: the named "class" of consumer entities (a product, a part, a ticket, ...) that attribute definitions attach to. |
|
value
Package value holds the AttributeValue aggregate: a typed value of an attribute definition, anchored to the consumer's own entity via EntityID.
|
Package value holds the AttributeValue aggregate: a typed value of an attribute definition, anchored to the consumer's own entity via EntityID. |
|
valueobjects
Package valueobjects holds the strongly-typed identifiers and value types shared across flexitype's domain.
|
Package valueobjects holds the strongly-typed identifiers and value types shared across flexitype's domain. |
|
examples
|
|
|
catalog/consumer
command
Command consumer is a minimal, production-shaped webhook receiver for flexitype events.
|
Command consumer is a minimal, production-shaped webhook receiver for flexitype events. |
|
infrastructure
|
|
|
memory
Package memory implements every flexitype repository port in process memory: no database, no migrations.
|
Package memory implements every flexitype repository port in process memory: no database, no migrations. |
|
postgres
Package postgres implements flexitype's repository ports over PostgreSQL.
|
Package postgres implements flexitype's repository ports over PostgreSQL. |
|
internal
|
|
|
config
Package config loads flexitype's service configuration from FLEXITYPE_* environment variables — twelve-factor style, no config files required.
|
Package config loads flexitype's service configuration from FLEXITYPE_* environment variables — twelve-factor style, no config files required. |
|
demo
Package demo seeds a small, feature-covering dataset: a type hierarchy (product → e-bike), attributes with constraints, entity values, a relationship with link attributes and a dependency — enough to explore every console screen and FQL construct.
|
Package demo seeds a small, feature-covering dataset: a type hierarchy (product → e-bike), attributes with constraints, entity values, a relationship with link attributes and a dependency — enough to explore every console screen and FQL construct. |
|
interfaces/http
Package http exposes flexitype's usecases as a versioned REST API for the standalone service.
|
Package http exposes flexitype's usecases as a versioned REST API for the standalone service. |
|
safedial
Package safedial builds HTTP clients that refuse to connect to private, loopback, link-local or otherwise non-public addresses.
|
Package safedial builds HTTP clients that refuse to connect to private, loopback, link-local or otherwise non-public addresses. |
|
shutdown
Package shutdown coordinates graceful teardown: tasks register with a priority and run highest-first when SIGINT/SIGTERM arrives, each bounded by the shutdown timeout.
|
Package shutdown coordinates graceful teardown: tasks register with a priority and run highest-first when SIGINT/SIGTERM arrives, each bounded by the shutdown timeout. |
|
telemetry
Package telemetry initialises OpenTelemetry tracing.
|
Package telemetry initialises OpenTelemetry tracing. |
|
testdb
Package testdb gives each DB-backed test package its own Postgres schema.
|
Package testdb gives each DB-backed test package its own Postgres schema. |
|
pkg
|
|
|
blob
Package blob is the object-storage port for media attribute values.
|
Package blob is the object-storage port for media attribute values. |
|
db
Package db defines the narrow database interfaces the rest of flexitype programs against, plus a sqlx-backed Transactor implementation with pre-commit / post-commit / rollback hooks.
|
Package db defines the narrow database interfaces the rest of flexitype programs against, plus a sqlx-backed Transactor implementation with pre-commit / post-commit / rollback hooks. |
|
deliverystats
Package deliverystats defines the event-delivery depth contract that the storage layer produces and the metrics layer consumes.
|
Package deliverystats defines the event-delivery depth contract that the storage layer produces and the metrics layer consumes. |
|
events
Package events defines flexitype's domain-event contract, the stable wire envelope subscribers receive, and a dispatcher with pluggable hooks so consumers can route events into their own infrastructure — a pub/sub broker, webhooks, or plain functions — without flexitype knowing about it.
|
Package events defines flexitype's domain-event contract, the stable wire envelope subscribers receive, and a dispatcher with pluggable hooks so consumers can route events into their own infrastructure — a pub/sub broker, webhooks, or plain functions — without flexitype knowing about it. |
|
formula
Package formula evaluates small arithmetic expressions over named inputs — the computation half of computed attributes.
|
Package formula evaluates small arithmetic expressions over named inputs — the computation half of computed attributes. |
|
fql
Package fql implements the flexitype query language: a lexer, a recursive-descent parser and a positioned AST.
|
Package fql implements the flexitype query language: a lexer, a recursive-descent parser and a positioned AST. |
|
health
Package health provides liveness/readiness checking with pluggable dependency checks, served at /healthz (process up) and /readyz (dependencies up).
|
Package health provides liveness/readiness checking with pluggable dependency checks, served at /healthz (process up) and /readyz (dependencies up). |
|
logger
Package logger wraps zerolog behind flexitype's logging conventions: structured JSON by default, console format for development, level from configuration.
|
Package logger wraps zerolog behind flexitype's logging conventions: structured JSON by default, console format for development, level from configuration. |
|
metrics
Package metrics exposes Prometheus SLIs for the standalone service: HTTP request rates and latencies, plus event-delivery depth gauges collected on scrape.
|
Package metrics exposes Prometheus SLIs for the standalone service: HTTP request rates and latencies, plus event-delivery depth gauges collected on scrape. |
|
ratelimit
Package ratelimit provides a per-key token-bucket limiter.
|
Package ratelimit provides a per-key token-bucket limiter. |
|
serviceaccount
Package serviceaccount implements machine-to-machine authentication for the standalone service.
|
Package serviceaccount implements machine-to-machine authentication for the standalone service. |
|
ulid
Package ulid wraps oklog/ulid/v2 behind a small, strongly-typed ID that knows how to travel through JSON, SQL and text encodings.
|
Package ulid wraps oklog/ulid/v2 behind a small, strongly-typed ID that knows how to travel through JSON, SQL and text encodings. |
|
Package web embeds the built admin console SPA.
|
Package web embeds the built admin console SPA. |