Forge Extension
Use Warden as a Forge extension with DI, routes, and lifecycle management.
Warden provides a first-class Forge extension that handles lifecycle, dependency injection, and API route registration.
Registration
import (
"github.com/xraph/forge"
wardenext "github.com/xraph/warden/extension"
)
app := forge.New()
app.Use(wardenext.New(
wardenext.WithConfig(wardenext.Config{
DisableRoutes: false, // Set true to skip API route registration
DisableMigrate: false, // Set true to skip auto-migration
}),
))
app.Start(context.Background())What the Extension Does
Register Phase
- Resolves a
store.Storefrom the Forge DI container - Creates a
warden.Enginewith the store and any configured options - Registers the engine in the DI container via
vessel.Provide() - If routes are enabled, registers REST API endpoints on
forge.Router
Start Phase
- Runs database migrations (unless
DisableMigrateis true) - Starts the engine
Stop Phase
- Gracefully shuts down the engine
- Fires
Shutdownhooks on all plugins
Extension options
| Option | Type | Default | Description |
|---|---|---|---|
WithStore(s) | store.Store | -- | Sets the persistence backend directly |
WithConfig(cfg) | Config | defaults | Extension configuration |
WithEngineOptions(opts...) | ...warden.Option | -- | Pass engine-level options |
WithPlugin(x) | plugin.Plugin | -- | Register a lifecycle plugin (repeatable) |
WithDisableRoutes() | -- | false | Skip HTTP route registration |
WithDisableMigrate() | -- | false | Skip migrations on Start |
WithBasePath(path) | string | "" | URL prefix for warden routes |
WithGroveDatabase(name) | string | "" | Named grove.DB to resolve from DI |
WithRequireConfig() | -- | false | Require config in YAML files |
Accessing the Engine
After registration, resolve the engine from any Forge handler:
func myHandler(ctx forge.Context) error {
eng := forge.Inject[*warden.Engine](ctx)
result, _ := eng.Check(ctx.Context(), &warden.CheckRequest{
Subject: warden.Subject{Kind: "user", ID: ctx.Get("userID")},
Action: "read",
ResourceType: "document",
})
if !result.Allowed {
return forge.Forbidden("access denied")
}
return ctx.JSON(200, data)
}Grove database integration
When your Forge app uses the Grove extension to manage database connections, Warden can automatically resolve a grove.DB from the DI container and construct the correct store backend based on the driver type.
Using the default grove database
If the Grove extension registers a single database (or a default in multi-DB mode), use WithGroveDatabase with an empty name:
ext := wardenext.New(
wardenext.WithGroveDatabase(""),
)Using a named grove database
In multi-database setups, reference a specific database by name:
ext := wardenext.New(
wardenext.WithGroveDatabase("warden"),
)This resolves the grove.DB named "warden" from the DI container and auto-constructs the matching store. The driver type is detected automatically -- you do not need to import individual store packages.
Store resolution order
The extension resolves its store in this order:
- Explicit store -- if
WithStore(s)was called, it is used directly and grove is ignored. - Grove database -- if
WithGroveDatabase(name)was called, the named or defaultgrove.DBis resolved from DI. - In-memory fallback -- if neither is configured, an in-memory store is used.
File-based configuration (YAML)
When running as a Forge extension, Warden automatically loads configuration from YAML config files. The extension looks for config under the following keys (in order):
extensions.warden-- standard Forge extension config namespacewarden-- top-level shorthand
Example
# forge.yaml
extensions:
warden:
disable_routes: false
disable_migrate: false
base_path: "/warden"
max_graph_depth: 10
grove_database: ""Config fields
| YAML Key | Type | Default | Description |
|---|---|---|---|
disable_routes | bool | false | Skip HTTP route registration |
disable_migrate | bool | false | Skip migrations on Start |
base_path | string | "" | URL prefix for all routes |
max_graph_depth | int | 10 | Max depth for ReBAC graph traversal |
grove_database | string | "" | Named grove.DB from DI |
Merge behaviour
File-based configuration is merged with programmatic options. Programmatic boolean flags (DisableRoutes, DisableMigrate) always win when set to true. For other fields, YAML values take precedence, then programmatic values, then defaults.
REST API Endpoints
When routes are enabled, the extension registers these endpoints:
| Method | Path | Description |
|---|---|---|
POST | /v1/authz/check | Authorization check |
POST | /v1/authz/enforce | Authorization enforce |
POST | /v1/authz/batch-check | Batch authorization check |
POST/GET/PUT/DELETE | /v1/roles/* | Role management |
POST/GET/DELETE | /v1/permissions/* | Permission management |
POST/GET/DELETE | /v1/assignments/* | Assignment management |
POST/GET | /v1/relations/* | Relation tuple management |
POST/GET/PUT/DELETE | /v1/policies/* | Policy management |
POST/GET/PUT/DELETE | /v1/resource-types/* | Resource type management |
GET | /v1/check-logs | Query check audit logs |
All endpoints include OpenAPI metadata for automatic documentation generation.