Documentation
¶
Overview ¶
Package module is wowapi's public module SDK: the contract a product module implements and the capability-scoped Context it registers against.
Modules live in consuming product repositories (see docs/blueprint/06-module-sdk.md and 11-framework-distribution-and- consumption.md); the framework repo keeps only private neutral fixtures under internal/testmodules.
Phase 0 ships the minimal contract (D-0006): Context grows one accessor at a time alongside the kernel capability each phase delivers (Routes in Phase 3, Authz in Phase 4, Migrations/Seeds in Phase 5, …). Interface widening is an accepted breaking change while wowapi is v0.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Context ¶
type Context interface {
// Logger returns a module-scoped structured logger (pre-tagged with the
// module name).
Logger() *slog.Logger
// Config returns the module's namespaced configuration view
// (modules.<name>.* only — see docs/blueprint/12 §2).
Config() config.ModuleView
// Routes returns the module's route registry. Every route must declare
// metadata (a permission or explicit public opt-out); registration errors
// surface at boot (Phase 3; blueprint 05 §1).
Routes() *httpx.Router
// Validator returns the shared request validator used by
// httpx.BindAndValidate (Phase 3).
Validator() *validation.Validator
// Permissions returns the authorization permission registry the module
// declares its permissions into; an unregistered permission can never be
// authorized (deny-by-default, boot-validated — Phase 4, blueprint 01 §3).
Permissions() *authz.Registry
// Resources returns the resource-type registry the module declares its
// resource types into (Phase 4).
Resources() *resource.Registry
// Authz returns the authorization evaluator for record-level checks and
// list filtering (Phase 4).
Authz() authz.Evaluator
// Tx returns the tenant transaction manager — the only door to the
// database for module work (Phase 2/5).
Tx() database.TxManager
// IDGen returns the id generator (UUIDv7); Clock returns the wall clock —
// both injectable so tests run deterministic sequences (Phase 5).
IDGen() model.IDGen
// Migrations registers the module's goose migrations. fsys must be ROOTED
// at the .sql files (use fs.Sub if they live in a subdirectory), matching
// goose's convention. Seeds registers its embedded YAML catalog bundle;
// OpenAPI registers its spec fragment. Applied/synced by the app at boot
// (Phase 5, blueprint 06 §2).
Migrations(fsys fs.FS)
Seeds(fsys fs.FS)
OpenAPI(fragment []byte)
// I18n registers a module's localized message bundle (GAP-001): the messages
// for one locale, keyed under the module's own "<name>." prefix. Called once
// per locale during Register (mirroring Seeds/OpenAPI collection). The app
// merges every module's bundles with the framework's own English catalog into
// one Catalog, which the httpx.Locale middleware negotiates against and
// WriteError/validation localize from. Product-specific translations stay in
// product-owned bundles — the framework ships only its own English strings.
I18n(bundle i18n.Bundle)
// Health registers a named readiness check (Phase 5).
Health(name string, check func(context.Context) error)
// ProvidePort declares an implementation another module may consume;
// Port fetches a declared port (both checked at boot — an unsatisfied
// Port dependency fails Validate). Inter-module access is via ports only,
// never another module's internals (Phase 5, blueprint 06 §2).
ProvidePort(name string, impl any)
Port(name string) (any, error)
// Events returns the event subscription registry (Subscribe an idempotent
// handler to an event type); Outbox returns the writer for emitting events
// in a business transaction (Phase 6, blueprint 07 §3/§7).
Events() *outbox.HandlerRegistry
Outbox() outbox.Writer
// Jobs returns the job-kind registry (RegisterKind → worker + retry policy).
// Enqueue is a package function (jobs.Enqueue) taking the business tx so a
// job commits atomically with the write (Phase 6).
Jobs() *jobs.Registry
// RecurringJob registers a leader-safe recurring job (roadmap E5/CA-5): the
// worker's scheduler runs fn once per active tenant every `every`, giving fn a
// tenant-bound DB in that tenant's transaction. The job name is prefixed with
// the module name to avoid collisions. Registration happens during Register;
// execution requires the worker process (the scheduler runs there). Interval
// scheduling ships first; cron syntax may follow.
RecurringJob(name string, every time.Duration, fn func(ctx context.Context, db database.TenantDB) error)
// Rules returns the rule-point registry (declare configurable rule points);
// RulesResolver returns the resolver for reading effective rule values.
// Workflows returns the workflow definition/action registry; WorkflowRuntime
// returns the runtime for driving instances (Phase 7, blueprint 02).
Rules() *rules.Registry
RulesResolver() *rules.Resolver
Workflows() *workflow.Registry
WorkflowRuntime() *workflow.Runtime
// RetentionClasses is the record-class registry a module declares its
// dispose/export/erase callbacks into during Register (roadmap E2); the kernel
// engine drives scheduled disposition and DSR fulfilment over them.
RetentionClasses() *retention.Registry
// Evidence-layer services (roadmap CA-11), all operating in the caller's tenant
// transaction:
// Audit — field-level change capture + per-tenant hash chain (S6/E1).
// Sequence — gap-free per-tenant numbered series (receipts/vouchers) (E3).
// Bulk — chunked, resumable bulk operations with a failure ledger (E6).
// Artifacts — immutable versioned artifacts (PDF/A + sidecar + hash) (E4).
Audit() *kaudit.Writer
Sequence() *sequence.Allocator
Bulk() *bulk.Service
Artifacts() *artifact.Pipeline
// Privileged returns the module's scoped privileged-service surface (GAP-006):
// the sanctioned, audited way to perform a valid tenant-scoped operation that
// needs PLATFORM privilege at the database — granting/revoking ReBAC
// relationship edges (Privileged().Relationships()) and activating tenant-scope
// rule versions (Privileged().Rules()) — WITHOUT the module writing its own
// SECURITY DEFINER SQL or ever seeing a platform pool. Each operation runs in a
// tenant-bound app_platform transaction and is restricted to relationship types
// and rule keys the module owns (module-name prefix ownership through this
// accessor), so a module can never manage another module's edges or rules.
// Products needing a wider allow-list construct their own privileged.New(...)
// at wiring time; see docs/user-guide/module-development.
Privileged() *privileged.Services
// Document / file framework (Phase 8, blueprint 07 §4). DocumentClasses is the
// registry a module declares its document classes into during Register;
// DocumentHooks registers OnFileUpload / OnDocumentAccess hooks. Documents is
// the runtime service (nil when the process has no object-storage adapter —
// boot fails if a module registered a class but no storage is wired). Comments
// and Attachments are plain services over any ResourceRef.
DocumentClasses() *document.Registry
DocumentHooks() *document.Hooks
Documents() *document.Service
Comments() *comment.Service
Attachments() *attachment.Service
// Notification / webhook / integration framework (Phase 9, blueprint 07 §5/§6).
// NotifyTemplates is the registry a module declares notification templates into
// during Register; Notify is the runtime send service. Webhooks registers
// inbound verifiers/handlers and drives inbound/outbound delivery.
// IntegrationProviders is the provider-adapter registry; Integrations resolves
// provider config + credentials.
NotifyTemplates() *notify.Registry
Notify() *notify.Service
Webhooks() *webhook.Service
IntegrationProviders() *integration.Registry
Integrations() *integration.Store
}
Context is the capability-scoped registration surface handed to Module.Register. Modules receive registries and services — never raw pools, never global config.
type Module ¶
type Module interface {
// Name is the unique module identifier: lowercase, [a-z][a-z0-9_]*,
// e.g. "requests". It prefixes permissions, resource types, events,
// rule points, and migration history entries.
Name() string
// DependsOn lists module names this module requires. The app topo-sorts
// registration by this graph; unknown names and cycles fail boot.
DependsOn() []string
// Register wires the module into the framework: routes, permissions,
// seeds, migrations, jobs, event handlers, … via ctx. Register must only
// wire — no I/O, no business logic.
Register(ctx Context) error
}
Module is implemented by every product module (and by the framework's private test fixtures).