From 54c2e18a19781e345bb16e7ce4bfb32b103199d3 Mon Sep 17 00:00:00 2001 From: Fred Amaral Date: Tue, 21 Jul 2026 19:48:27 -0300 Subject: [PATCH 1/2] feat(core)!: port to v2 line on fiber v3 stack Major line bump: module github.com/LerianStudio/lib-systemplane/v2. - gofiber/fiber/v2 -> v3 (Ctx is now an interface; UserContext -> Context, BodyParser -> Bind().Body, app.Test TestConfig) - lib-commons/v5 v5.8.0 -> /v6 v6.0.0 (import-path churn only) - lib-observability v1.1.0 -> /v2 v2.0.0 (import-path churn only) - All self-imports moved to /v2; docs and examples updated No feature behavior changed; ddl/ and LISTEN/NOTIFY untouched. BREAKING CHANGE: module path is now github.com/LerianStudio/lib-systemplane/v2. admin.WithAuthorizer and admin.WithActorExtractor now take fiber.Ctx (v3 interface) instead of *fiber.Ctx. X-Lerian-Ref: 0x1 Claude-Session: https://claude.ai/code/session_019CPR8BaUFL4TuPVos9DGds --- .env.reference | 6 +- CLAUDE.md | 16 ++--- README.md | 40 ++++++------ admin/admin.go | 62 +++++++++---------- admin/admin_responses.go | 8 +-- admin/admin_test.go | 36 +++++------ api_client.go | 4 +- api_constants.go | 2 +- api_constructors.go | 6 +- api_errors.go | 2 +- api_testing.go | 2 +- api_types.go | 2 +- ddl_test.go | 2 +- docs/PROJECT_RULES.md | 12 ++-- examples/manager/main.go | 6 +- go.mod | 14 +++-- go.sum | 30 ++++++--- internal/client/catalog_test.go | 2 +- internal/client/client.go | 16 ++--- internal/client/client_telemetry.go | 2 +- internal/client/client_test.go | 2 +- internal/client/client_testing.go | 2 +- internal/client/errors.go | 2 +- internal/client/get.go | 4 +- internal/client/manager_binding.go | 2 +- internal/client/manager_binding_test.go | 2 +- internal/client/onchange.go | 2 +- internal/client/options.go | 4 +- internal/client/redact.go | 2 +- internal/client/set.go | 2 +- internal/client/testing_facade_test.go | 2 +- internal/debounce/debounce.go | 4 +- internal/manager/connector.go | 2 +- .../connector_pgmgr_integration_test.go | 2 +- internal/manager/connector_pgmgr_test.go | 2 +- internal/manager/events.go | 4 +- internal/manager/get.go | 2 +- internal/manager/goleak_integration_test.go | 2 +- internal/manager/handle_lifecycle.go | 4 +- internal/manager/handle_lifecycle_test.go | 4 +- internal/manager/internal_test.go | 2 +- internal/manager/lifecycle.go | 2 +- internal/manager/listen.go | 6 +- internal/manager/listen_integration_test.go | 2 +- internal/manager/logging.go | 2 +- internal/manager/manager.go | 6 +- internal/manager/manager_integration_test.go | 6 +- internal/manager/manager_test.go | 2 +- internal/manager/metrics.go | 4 +- internal/manager/metrics_helper_test.go | 2 +- internal/manager/metrics_test.go | 2 +- internal/manager/warmload.go | 2 +- internal/mongodb/mongodb.go | 8 +-- internal/mongodb/mongodb_changestream.go | 8 +-- internal/mongodb/mongodb_changestream_test.go | 2 +- internal/mongodb/mongodb_config.go | 2 +- internal/mongodb/mongodb_crud.go | 2 +- internal/mongodb/mongodb_events.go | 4 +- .../mongodb_goleak_integration_test.go | 4 +- internal/mongodb/mongodb_integration_test.go | 8 +-- .../mongodb_polling_integration_test.go | 2 +- internal/mongodb/mongodb_unit_test.go | 2 +- internal/postgres/postgres.go | 8 +-- internal/postgres/postgres_config.go | 2 +- .../postgres_goleak_integration_test.go | 4 +- .../postgres/postgres_integration_test.go | 10 +-- internal/postgres/postgres_listen.go | 8 +-- internal/postgres/postgres_listen_test.go | 2 +- internal/postgres/postgres_notify.go | 4 +- internal/postgres/postgres_unit_test.go | 2 +- manager.go | 10 +-- manager_methods.go | 4 +- manager_methods_test.go | 4 +- systemplanetest/contract.go | 2 +- 74 files changed, 237 insertions(+), 225 deletions(-) diff --git a/.env.reference b/.env.reference index e2a3f12..c623ced 100644 --- a/.env.reference +++ b/.env.reference @@ -139,17 +139,17 @@ SYSTEMPLANE_ADMIN_PATH_PREFIX=/system # Code-only admin options — NO env-var representation: # -# admin.WithAuthorizer(fn func(*fiber.Ctx, action string) error) +# admin.WithAuthorizer(fn func(fiber.Ctx, action string) error) # Required to enable the three legacy global routes. Absent = 403 on every # legacy route. Takes a function value; cannot be expressed as an env var. # -# admin.WithTenantAuthorizer(fn func(*fiber.Ctx, action, tenantID string) error) +# admin.WithTenantAuthorizer(fn func(fiber.Ctx, action, tenantID string) error) # Required to enable the three tenant-scoped routes. Absent = 403 on every # tenant route (default-deny). The library does NOT silently fall back to # WithAuthorizer for tenant routes — consumers must opt in explicitly to # avoid silent privilege escalation. Takes a function value. # -# admin.WithActorExtractor(fn func(*fiber.Ctx) string) +# admin.WithActorExtractor(fn func(fiber.Ctx) string) # Customizes how the actor identity is extracted from a Fiber request for # audit logging on writes. Takes a function value. diff --git a/CLAUDE.md b/CLAUDE.md index 0b92474..f43164e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,10 +4,10 @@ This file provides repository-specific guidance for coding agents working on `li ## Project snapshot -- Module: `github.com/LerianStudio/lib-systemplane` +- Module: `github.com/LerianStudio/lib-systemplane/v2` - Language: Go - Go version: `1.26.3` (see `go.mod`) -- Current API generation: v1.x observability migration (extracted from `lib-commons/v5`; public observability types now come from `lib-observability`) +- Current API generation: v2.x Fiber v3 stack (extracted from `lib-commons/v5`; built on `lib-commons/v6`, `lib-observability/v2`, and `gofiber/fiber/v3`) ## Primary objective for changes @@ -21,7 +21,7 @@ This file provides repository-specific guidance for coding agents working on `li Root (package `systemplane`): - Small public API facade: `api_*.go` plus `doc.go`. Public types are aliases to `internal/client` where practical so the root import path remains - `github.com/LerianStudio/lib-systemplane`. + `github.com/LerianStudio/lib-systemplane/v2`. Subpackages: - `admin/` — Fiber HTTP handlers for the admin surface @@ -44,9 +44,9 @@ Scaffolding: Lerian shared-library boundaries are now split across four libraries: -- `github.com/LerianStudio/lib-commons/v5` — non-observability shared primitives used here: `commons/tenant-manager/core`, `commons/net/http`, and `commons/backoff`. -- `github.com/LerianStudio/lib-observability` — canonical observability stack: `log`, `tracing`, redaction helpers, span helpers, telemetry lifecycle, and `runtime` panic recovery. -- `github.com/LerianStudio/lib-systemplane` — this module; runtime-mutable configuration with Postgres/MongoDB backends. +- `github.com/LerianStudio/lib-commons/v6` — non-observability shared primitives used here: `commons/tenant-manager/core`, `commons/net/http`, and `commons/backoff`. +- `github.com/LerianStudio/lib-observability/v2` — canonical observability stack: `log`, `tracing`, redaction helpers, span helpers, telemetry lifecycle, and `runtime` panic recovery. +- `github.com/LerianStudio/lib-systemplane/v2` — this module; runtime-mutable configuration with Postgres/MongoDB backends. - `github.com/LerianStudio/lib-streaming` — tenant-scoped event streaming; do not introduce it here unless a task explicitly asks for streaming integration. These are external module imports. Do not rewrite them to in-repo paths. Do not reintroduce observability imports from `lib-commons`; observability has moved to `lib-observability`. @@ -58,7 +58,7 @@ These are external module imports. Do not rewrite them to in-repo paths. Do not The Client runs in one of two modes selected at construction: - **Single-tenant** (default). The constructor receives a non-nil `*sql.DB` / `*mongo.Client`. Reads serve from an in-process cache; writes upsert through the store and update the cache. The backend's changefeed (LISTEN/NOTIFY on Postgres, change stream on MongoDB) drives invalidation and fires `OnChange` subscribers. -- **Multi-tenant** (opt-in via `WithMultiTenantEnabled()`). DB/client may be nil. Every read/write resolves the tenant database from `ctx` via `tmcore.GetPGContext(ctx, module)` / `tmcore.GetMBContext(ctx, module)` (`lib-commons/v5/commons/tenant-manager/core`). For Postgres the lib performs NO runtime schema provisioning — `systemplane_entries` plus its NOTIFY trigger function/triggers must be created externally via `SchemaSQL()` / `DefaultSeedSQL()` (e.g. the consumer's migration pipeline); the runtime role only needs DML + `LISTEN`. (MongoDB still bootstraps its collection/indexes lazily once per resolved tenant database via a `sync.Map`-backed `sync.Once` cache.) No in-process cache. No LISTEN/NOTIFY. `OnChange` returns `ErrNotSupportedInMultiTenant`. Callers wire `tenant-manager/middleware.TenantMiddleware` (with `WithPG(...)` or `WithMB(...)` and a matching module name) before the lib's handlers. +- **Multi-tenant** (opt-in via `WithMultiTenantEnabled()`). DB/client may be nil. Every read/write resolves the tenant database from `ctx` via `tmcore.GetPGContext(ctx, module)` / `tmcore.GetMBContext(ctx, module)` (`lib-commons/v6/commons/tenant-manager/core`). For Postgres the lib performs NO runtime schema provisioning — `systemplane_entries` plus its NOTIFY trigger function/triggers must be created externally via `SchemaSQL()` / `DefaultSeedSQL()` (e.g. the consumer's migration pipeline); the runtime role only needs DML + `LISTEN`. (MongoDB still bootstraps its collection/indexes lazily once per resolved tenant database via a `sync.Map`-backed `sync.Once` cache.) No in-process cache. No LISTEN/NOTIFY. `OnChange` returns `ErrNotSupportedInMultiTenant`. Callers wire `tenant-manager/middleware.TenantMiddleware` (with `WithPG(...)` or `WithMB(...)` and a matching module name) before the lib's handlers. ### Storage shape @@ -81,7 +81,7 @@ The Client runs in one of two modes selected at construction: - Subscriptions: `OnChange(ns, key, fn) (unsubscribe func(), error)`. Returns `ErrNotSupportedInMultiTenant` in multi-tenant mode. Callbacks invoked serially with panic recovery via `lib-observability/runtime.RecoverAndLog`. - Registered keys carry: default value, description, validator func, redaction policy (`RedactNone | RedactMask | RedactFull`). Options: `WithDescription`, `WithValidator`, `WithRedaction`. - Client options: `WithLogger`, `WithTelemetry`, `WithDebounce` (default 100ms), `WithListenChannel` (Postgres default `"systemplane_changes"`), `WithTable` (Postgres default `"systemplane_entries"`), `WithCollection` (MongoDB default `"systemplane_entries"`), `WithPollInterval` (MongoDB — switches to polling), `WithMultiTenantEnabled()`, `WithModule(name)` (default `"systemplane"`). -- Admin HTTP surface (`admin` subpackage): `Mount(router, client, opts...)` registers four routes at a configurable prefix (default `/system`): `GET :prefix/:namespace`, `GET :prefix/:namespace/:key`, `PUT :prefix/:namespace/:key`, `DELETE :prefix/:namespace/:key`. Options: `WithPathPrefix`, `WithAuthorizer(fn func(*fiber.Ctx, action string) error)` — default-deny — and `WithActorExtractor`. The `action` argument is `"read"` (GET) or `"write"` (PUT/DELETE). In multi-tenant mode the caller MUST mount tenant-manager middleware before `admin.Mount` so handler `c.UserContext()` carries the resolved tenant database. +- Admin HTTP surface (`admin` subpackage): `Mount(router, client, opts...)` registers four routes at a configurable prefix (default `/system`): `GET :prefix/:namespace`, `GET :prefix/:namespace/:key`, `PUT :prefix/:namespace/:key`, `DELETE :prefix/:namespace/:key`. Options: `WithPathPrefix`, `WithAuthorizer(fn func(fiber.Ctx, action string) error)` — default-deny — and `WithActorExtractor`. The `action` argument is `"read"` (GET) or `"write"` (PUT/DELETE). In multi-tenant mode the caller MUST mount tenant-manager middleware before `admin.Mount` so handler `c.Context()` carries the resolved tenant database. - Internal `Store` interface (`internal/store`): `Start`, `Close`, `Get`, `Set`, `Delete`, `List`, `Subscribe`. Implemented by `internal/postgres` and `internal/mongodb`. Backend-agnostic contract suite lives in `systemplanetest.Run(t, factory, RunOptions{SkipSubscribe: ...})` — multi-tenant modes pass `SkipSubscribe: true`. - Sentinel errors: `ErrClosed`, `ErrNotStarted`, `ErrRegisterAfterStart`, `ErrUnknownKey`, `ErrValidation`, `ErrDuplicateKey`, `ErrNilContext`, `ErrNotSupportedInMultiTenant`, `ErrTenantConnectionMissing`. - `NewForTesting(s TestStore, opts ...Option) (*Client, error)` is an explicit out-of-package test helper. Build-tag gated (`unit`/`integration`); not a promised production API. diff --git a/README.md b/README.md index 29ebf8b..1ee055d 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,20 @@ # lib-systemplane -Dual-backend (PostgreSQL / MongoDB) hot-reload runtime configuration for Lerian services. Register operational knobs (log levels, feature flags, rate limits, circuit-breaker thresholds, worker intervals) at startup, mutate them at runtime without a pod restart, and — in single-tenant mode — subscribe to change events through a LISTEN/NOTIFY (Postgres) or change-stream (MongoDB) backed subscription. First-class support for the Lerian database-per-tenant model via the `lib-commons/v5` tenant-manager dispatch layer. +Dual-backend (PostgreSQL / MongoDB) hot-reload runtime configuration for Lerian services. Register operational knobs (log levels, feature flags, rate limits, circuit-breaker thresholds, worker intervals) at startup, mutate them at runtime without a pod restart, and — in single-tenant mode — subscribe to change events through a LISTEN/NOTIFY (Postgres) or change-stream (MongoDB) backed subscription. First-class support for the Lerian database-per-tenant model via the `lib-commons/v6` tenant-manager dispatch layer. -This library was extracted from `lib-commons/v5/commons/systemplane`. The v1 line uses `lib-observability` for logging, tracing, telemetry, redaction, and panic recovery. +This library was extracted from `lib-commons/v5/commons/systemplane`. The v2 line targets the Fiber v3 stack (`lib-commons/v6`) and uses `lib-observability/v2` for logging, tracing, telemetry, redaction, and panic recovery. ## Requirements - Go `1.26.3` or newer - PostgreSQL 13+ **or** MongoDB 4.4+ (replica set required for change streams; polling fallback available for standalone MongoDB) -- `github.com/LerianStudio/lib-commons/v5` for tenant-manager context, admin HTTP helpers, and backoff -- `github.com/LerianStudio/lib-observability` for logging, tracing, telemetry, redaction, and panic recovery +- `github.com/LerianStudio/lib-commons/v6` for tenant-manager context, admin HTTP helpers, and backoff +- `github.com/LerianStudio/lib-observability/v2` for logging, tracing, telemetry, redaction, and panic recovery ## Installation ```bash -go get github.com/LerianStudio/lib-systemplane +go get github.com/LerianStudio/lib-systemplane/v2 ``` ## Operating modes @@ -26,7 +26,7 @@ The library supports two modes; pick at construction time: | Single-tenant | `db *sql.DB` / `*mongo.Client` | In-process cache | Through cache + store | LISTEN/NOTIFY (Postgres) or change stream (MongoDB) | | Multi-tenant | May be nil | Resolved per-call via tenant-manager ctx | Same | Disabled — `OnChange` returns `ErrNotSupportedInMultiTenant` | -In multi-tenant mode the library does NOT hold an in-process cache. Every `Get` reads through the resolved tenant database. The lib expects the caller to wire `lib-commons/v5/commons/tenant-manager/middleware.TenantMiddleware` with `WithPG(pgManager, "")` (Postgres) or `WithMB(mongoManager, "")` (MongoDB) where `` matches the lib's `WithModule(...)` option (default `"systemplane"`). The middleware populates the request context; the lib calls `tmcore.GetPGContext` / `tmcore.GetMBContext` to resolve the tenant database and runs the read/write against that handle. +In multi-tenant mode the library does NOT hold an in-process cache. Every `Get` reads through the resolved tenant database. The lib expects the caller to wire `lib-commons/v6/commons/tenant-manager/middleware.TenantMiddleware` with `WithPG(pgManager, "")` (Postgres) or `WithMB(mongoManager, "")` (MongoDB) where `` matches the lib's `WithModule(...)` option (default `"systemplane"`). The middleware populates the request context; the lib calls `tmcore.GetPGContext` / `tmcore.GetMBContext` to resolve the tenant database and runs the read/write against that handle. > **Provisioning (Postgres).** The library no longer creates its schema or seeds defaults at runtime. Provision `systemplane_entries` (plus the `systemplane_notify_v3()` trigger function and the NOTIFY triggers) and any defaults externally — e.g. via your migration pipeline — using the DDL published by [`SchemaSQL()` / `DefaultSeedSQL()`](#schema-provisioning). The runtime database role only needs DML (`SELECT`/`INSERT`/`UPDATE`/`DELETE`) + `LISTEN`; it does NOT need `CREATE` on the schema. @@ -61,7 +61,7 @@ import ( "os" _ "github.com/jackc/pgx/v5/stdlib" - systemplane "github.com/LerianStudio/lib-systemplane" + systemplane "github.com/LerianStudio/lib-systemplane/v2" ) func main() { @@ -130,7 +130,7 @@ import ( "go.mongodb.org/mongo-driver/v2/mongo" "go.mongodb.org/mongo-driver/v2/mongo/options" - systemplane "github.com/LerianStudio/lib-systemplane" + systemplane "github.com/LerianStudio/lib-systemplane/v2" ) func main() { @@ -186,10 +186,10 @@ import ( "fmt" "os" - tmpostgres "github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/postgres" - tmmiddleware "github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/middleware" - systemplane "github.com/LerianStudio/lib-systemplane" - "github.com/gofiber/fiber/v2" + tmpostgres "github.com/LerianStudio/lib-commons/v6/commons/tenant-manager/postgres" + tmmiddleware "github.com/LerianStudio/lib-commons/v6/commons/tenant-manager/middleware" + systemplane "github.com/LerianStudio/lib-systemplane/v2" + "github.com/gofiber/fiber/v3" ) func main() { @@ -234,8 +234,8 @@ func run() error { tmmiddleware.WithPG(pgManager, "systemplane"), )) - app.Get("/log-level", func(c *fiber.Ctx) error { - level, _, err := client.GetString(c.UserContext(), "global", "log.level") + app.Get("/log-level", func(c fiber.Ctx) error { + level, _, err := client.GetString(c.Context(), "global", "log.level") if err != nil { return err } @@ -255,10 +255,10 @@ package main import ( "context" - tmmongo "github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/mongo" - tmmiddleware "github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/middleware" - systemplane "github.com/LerianStudio/lib-systemplane" - "github.com/gofiber/fiber/v2" + tmmongo "github.com/LerianStudio/lib-commons/v6/commons/tenant-manager/mongo" + tmmiddleware "github.com/LerianStudio/lib-commons/v6/commons/tenant-manager/middleware" + systemplane "github.com/LerianStudio/lib-systemplane/v2" + "github.com/gofiber/fiber/v3" ) func run() error { @@ -303,7 +303,7 @@ In multi-tenant mode the lib does NOT provision schema at runtime for Postgres Mount the Fiber admin surface under a configurable path prefix (default `/system`): ```go -import "github.com/LerianStudio/lib-systemplane/admin" +import "github.com/LerianStudio/lib-systemplane/v2/admin" admin.Mount(app, client, admin.WithPathPrefix("/system"), @@ -320,7 +320,7 @@ PUT //:namespace/:key - write a single entry DELETE //:namespace/:key - delete a single entry ``` -In multi-tenant mode, authenticate before tenant resolution, then mount the tenant-manager middleware BEFORE `admin.Mount` so handler `c.UserContext()` carries the tenant database. +In multi-tenant mode, authenticate before tenant resolution, then mount the tenant-manager middleware BEFORE `admin.Mount` so handler `c.Context()` carries the tenant database. ### Catalog routes diff --git a/admin/admin.go b/admin/admin.go index 1319302..0948130 100644 --- a/admin/admin.go +++ b/admin/admin.go @@ -25,7 +25,7 @@ // // In multi-tenant mode the caller is expected to run authentication before // lib-commons tenant-manager middleware, then call Mount so handlers' -// c.UserContext() carries the resolved tenant database for the lib's +// c.Context() carries the resolved tenant database for the lib's // configured module. package admin @@ -37,10 +37,10 @@ import ( "net/url" "strings" - commonshttp "github.com/LerianStudio/lib-commons/v5/commons/net/http" - "github.com/LerianStudio/lib-observability/log" - systemplane "github.com/LerianStudio/lib-systemplane" - "github.com/gofiber/fiber/v2" + commonshttp "github.com/LerianStudio/lib-commons/v6/commons/net/http" + "github.com/LerianStudio/lib-observability/v2/log" + systemplane "github.com/LerianStudio/lib-systemplane/v2" + "github.com/gofiber/fiber/v3" ) const ( @@ -53,17 +53,17 @@ const ( // mountConfig holds options applied by MountOption functions. type mountConfig struct { pathPrefix string - authorizer func(*fiber.Ctx, string) error - actorExtractor func(*fiber.Ctx) string + authorizer func(fiber.Ctx, string) error + actorExtractor func(fiber.Ctx) string } func defaultMountConfig() mountConfig { return mountConfig{ pathPrefix: "/system", - authorizer: func(_ *fiber.Ctx, _ string) error { + authorizer: func(_ fiber.Ctx, _ string) error { return errors.New("admin: no authorizer configured — use admin.WithAuthorizer to set one") }, - actorExtractor: func(_ *fiber.Ctx) string { return "" }, + actorExtractor: func(_ fiber.Ctx) string { return "" }, } } @@ -82,7 +82,7 @@ func WithPathPrefix(p string) MountOption { // WithAuthorizer sets an authorization check called before each handler. The // action argument is "read" for GET requests and "write" for PUT/DELETE // requests. Return a non-nil error to reject the request with 403 Forbidden. -func WithAuthorizer(fn func(*fiber.Ctx, string) error) MountOption { +func WithAuthorizer(fn func(fiber.Ctx, string) error) MountOption { return func(cfg *mountConfig) { if fn != nil { cfg.authorizer = fn @@ -93,7 +93,7 @@ func WithAuthorizer(fn func(*fiber.Ctx, string) error) MountOption { // WithActorExtractor sets a function that extracts the actor identity from // the request context; the returned string is passed as the actor argument // to [systemplane.Client.Set] and [systemplane.Client.Delete]. -func WithActorExtractor(fn func(*fiber.Ctx) string) MountOption { +func WithActorExtractor(fn func(fiber.Ctx) string) MountOption { return func(cfg *mountConfig) { if fn != nil { cfg.actorExtractor = fn @@ -169,9 +169,9 @@ func normalizePathPrefix(prefix string) string { } func authorize(cfg mountConfig, logger log.Logger, action string) fiber.Handler { - return func(c *fiber.Ctx) error { + return func(c fiber.Ctx) error { if err := cfg.authorizer(c, action); err != nil { - logger.Log(c.UserContext(), log.LevelDebug, "admin: authorizer denied", + logger.Log(c.Context(), log.LevelDebug, "admin: authorizer denied", log.String("action", action), log.Err(err), ) @@ -183,7 +183,7 @@ func authorize(cfg mountConfig, logger log.Logger, action string) fiber.Handler } } -func validateNamespaceParam(c *fiber.Ctx) error { +func validateNamespaceParam(c fiber.Ctx) error { if ns := c.Params("namespace"); len(ns) > maxNamespaceLen { return commonshttp.RespondError(c, http.StatusBadRequest, "validation_error", fmt.Sprintf("namespace exceeds maximum length of %d", maxNamespaceLen)) @@ -192,15 +192,15 @@ func validateNamespaceParam(c *fiber.Ctx) error { return c.Next() } -func validatePathParams(c *fiber.Ctx) error { +func validatePathParams(c fiber.Ctx) error { return validateParamLengths(c, c.Params("namespace"), c.Params("key")) } -func validateWildcardPathParams(c *fiber.Ctx) error { +func validateWildcardPathParams(c fiber.Ctx) error { return validateParamLengths(c, c.Params("namespace"), c.Params("*")) } -func validateParamLengths(c *fiber.Ctx, namespace, key string) error { +func validateParamLengths(c fiber.Ctx, namespace, key string) error { if len(namespace) > maxNamespaceLen { return commonshttp.RespondError(c, http.StatusBadRequest, "validation_error", fmt.Sprintf("namespace exceeds maximum length of %d", maxNamespaceLen)) @@ -215,10 +215,10 @@ func validateParamLengths(c *fiber.Ctx, namespace, key string) error { } func handleList(client *systemplane.Client) fiber.Handler { - return func(c *fiber.Ctx) error { + return func(c fiber.Ctx) error { namespace := c.Params("namespace") - entries, err := client.List(c.UserContext(), namespace) + entries, err := client.List(c.Context(), namespace) if err != nil { return mapSentinelErr(c, err) } @@ -244,7 +244,7 @@ func handleList(client *systemplane.Client) fiber.Handler { } func handleCatalogList(client *systemplane.Client, prefix string) fiber.Handler { - return func(c *fiber.Ctx) error { + return func(c fiber.Ctx) error { catalog := client.Catalog() for i := range catalog.Keys { catalog.Keys[i].DetailURL = catalogDetailPath(prefix, catalog.Keys[i].Namespace, catalog.Keys[i].Key) @@ -255,7 +255,7 @@ func handleCatalogList(client *systemplane.Client, prefix string) fiber.Handler } func handleCatalogDetail(client *systemplane.Client, prefix string) fiber.Handler { - return func(c *fiber.Ctx) error { + return func(c fiber.Ctx) error { detail, namespace, key, ok := catalogDetailFromParams(client, c.Params("namespace"), routeKeyParam(c)) if !ok { return commonshttp.RespondError(c, http.StatusNotFound, "not_found", "systemplane catalog entry not found") @@ -290,7 +290,7 @@ func valuePath(prefix, namespace, key string) string { return fmt.Sprintf("%s/%s/%s", prefix, url.PathEscape(namespace), url.PathEscape(key)) } -func routeKeyParam(c *fiber.Ctx) string { +func routeKeyParam(c fiber.Ctx) string { if key := c.Params("key"); key != "" { return key } @@ -298,7 +298,7 @@ func routeKeyParam(c *fiber.Ctx) string { return c.Params("*") } -func registeredPathParams(client *systemplane.Client, c *fiber.Ctx) (string, string) { +func registeredPathParams(client *systemplane.Client, c fiber.Ctx) (string, string) { namespaceParam := c.Params("namespace") keyParam := routeKeyParam(c) @@ -351,10 +351,10 @@ func catalogRedactionPolicy(redaction string) systemplane.RedactPolicy { } func handleGetOne(client *systemplane.Client) fiber.Handler { - return func(c *fiber.Ctx) error { + return func(c fiber.Ctx) error { namespace, key := registeredPathParams(client, c) - value, ok, err := client.Get(c.UserContext(), namespace, key) + value, ok, err := client.Get(c.Context(), namespace, key) if err != nil { return mapSentinelErr(c, err) } @@ -376,7 +376,7 @@ func handleGetOne(client *systemplane.Client) fiber.Handler { } func handlePut(client *systemplane.Client, cfg mountConfig) fiber.Handler { - return func(c *fiber.Ctx) error { + return func(c fiber.Ctx) error { namespace, key := registeredPathParams(client, c) value, badRequestMsg := decodePutValue(c) @@ -386,7 +386,7 @@ func handlePut(client *systemplane.Client, cfg mountConfig) fiber.Handler { actor := cfg.actorExtractor(c) - if err := client.Set(c.UserContext(), namespace, key, value, actor); err != nil { + if err := client.Set(c.Context(), namespace, key, value, actor); err != nil { return mapSentinelErr(c, err) } @@ -395,12 +395,12 @@ func handlePut(client *systemplane.Client, cfg mountConfig) fiber.Handler { } func handleDelete(client *systemplane.Client, cfg mountConfig) fiber.Handler { - return func(c *fiber.Ctx) error { + return func(c fiber.Ctx) error { namespace, key := registeredPathParams(client, c) actor := cfg.actorExtractor(c) - if err := client.Delete(c.UserContext(), namespace, key, actor); err != nil { + if err := client.Delete(c.Context(), namespace, key, actor); err != nil { return mapSentinelErr(c, err) } @@ -408,9 +408,9 @@ func handleDelete(client *systemplane.Client, cfg mountConfig) fiber.Handler { } } -func decodePutValue(c *fiber.Ctx) (any, string) { +func decodePutValue(c fiber.Ctx) (any, string) { var body putRequest - if err := c.BodyParser(&body); err != nil { + if err := c.Bind().Body(&body); err != nil { return nil, "invalid request body" } diff --git a/admin/admin_responses.go b/admin/admin_responses.go index d734651..c3cad6f 100644 --- a/admin/admin_responses.go +++ b/admin/admin_responses.go @@ -6,9 +6,9 @@ import ( "errors" "net/http" - commonshttp "github.com/LerianStudio/lib-commons/v5/commons/net/http" - systemplane "github.com/LerianStudio/lib-systemplane" - "github.com/gofiber/fiber/v2" + commonshttp "github.com/LerianStudio/lib-commons/v6/commons/net/http" + systemplane "github.com/LerianStudio/lib-systemplane/v2" + "github.com/gofiber/fiber/v3" ) type listResponse struct { @@ -46,7 +46,7 @@ type putRequest struct { Value json.RawMessage `json:"value"` } -func mapSentinelErr(c *fiber.Ctx, err error) error { +func mapSentinelErr(c fiber.Ctx, err error) error { switch { case errors.Is(err, systemplane.ErrUnknownKey): return commonshttp.RespondError(c, http.StatusBadRequest, "unknown_key", "key is not registered") diff --git a/admin/admin_test.go b/admin/admin_test.go index d0c3358..b0bf075 100644 --- a/admin/admin_test.go +++ b/admin/admin_test.go @@ -14,10 +14,10 @@ import ( "testing" "time" - obsconstants "github.com/LerianStudio/lib-observability/constants" - systemplane "github.com/LerianStudio/lib-systemplane" - "github.com/LerianStudio/lib-systemplane/admin" - "github.com/gofiber/fiber/v2" + obsconstants "github.com/LerianStudio/lib-observability/v2/constants" + systemplane "github.com/LerianStudio/lib-systemplane/v2" + "github.com/LerianStudio/lib-systemplane/v2/admin" + "github.com/gofiber/fiber/v3" ) // fakeStore is an in-memory implementation of systemplane.TestStore used to @@ -171,10 +171,10 @@ func setupClientWithOptions( func mountAndRun(t *testing.T, c *systemplane.Client, opts ...admin.MountOption) *fiber.App { t.Helper() - app := fiber.New(fiber.Config{DisableStartupMessage: true}) + app := fiber.New() defaults := []admin.MountOption{ - admin.WithAuthorizer(func(_ *fiber.Ctx, _ string) error { return nil }), - admin.WithActorExtractor(func(_ *fiber.Ctx) string { return "tester" }), + admin.WithAuthorizer(func(_ fiber.Ctx, _ string) error { return nil }), + admin.WithActorExtractor(func(_ fiber.Ctx) string { return "tester" }), } admin.Mount(app, c, append(defaults, opts...)...) @@ -185,10 +185,10 @@ func mountAndRun(t *testing.T, c *systemplane.Client, opts ...admin.MountOption) func mountCatalogAndRun(t *testing.T, c *systemplane.Client, opts ...admin.MountOption) *fiber.App { t.Helper() - app := fiber.New(fiber.Config{DisableStartupMessage: true}) + app := fiber.New() defaults := []admin.MountOption{ - admin.WithAuthorizer(func(_ *fiber.Ctx, _ string) error { return nil }), - admin.WithActorExtractor(func(_ *fiber.Ctx) string { return "tester" }), + admin.WithAuthorizer(func(_ fiber.Ctx, _ string) error { return nil }), + admin.WithActorExtractor(func(_ fiber.Ctx) string { return "tester" }), } admin.MountCatalog(app, c, append(defaults, opts...)...) @@ -204,7 +204,7 @@ func doRequest(t *testing.T, app *fiber.App, method, path, body string) *http.Re req.Header.Set("Content-Type", "application/json") } - resp, err := app.Test(req, int(2*time.Second/time.Millisecond)) + resp, err := app.Test(req, fiber.TestConfig{Timeout: 2 * time.Second}) if err != nil { t.Fatalf("app.Test: %v", err) } @@ -404,7 +404,7 @@ func TestAdmin_ListNamespace(t *testing.T) { func TestAdmin_DenyByDefault(t *testing.T) { c, _ := setupClient(t, nil) - app := fiber.New(fiber.Config{DisableStartupMessage: true}) + app := fiber.New() // Mount WITHOUT WithAuthorizer — should deny. admin.Mount(app, c) @@ -461,13 +461,13 @@ func TestAdmin_CatalogListAndDetail(t *testing.T) { return c.Register("tenant", "enabled", true) }) - app := fiber.New(fiber.Config{DisableStartupMessage: true}) - authorizer := admin.WithAuthorizer(func(_ *fiber.Ctx, action string) error { + app := fiber.New() + authorizer := admin.WithAuthorizer(func(_ fiber.Ctx, action string) error { actions = append(actions, action) return nil }) admin.MountCatalog(app, c, authorizer) - admin.Mount(app, c, authorizer, admin.WithActorExtractor(func(*fiber.Ctx) string { return "tester" })) + admin.Mount(app, c, authorizer, admin.WithActorExtractor(func(fiber.Ctx) string { return "tester" })) resp := doRequest(t, app, http.MethodGet, "/system/-/catalog", "") if resp.StatusCode != http.StatusOK { @@ -666,7 +666,7 @@ func TestAdmin_CatalogUnknownDetailReturnsNotFound(t *testing.T) { func TestAdmin_CatalogDenyByDefault(t *testing.T) { c, _ := setupClient(t, nil) - app := fiber.New(fiber.Config{DisableStartupMessage: true}) + app := fiber.New() admin.MountCatalog(app, c) resp := doRequest(t, app, http.MethodGet, "/system/-/catalog", "") @@ -775,10 +775,10 @@ func TestAdmin_CatalogDoesNotRedactExamples(t *testing.T) { func TestAdmin_CatalogUsesReadAuthorization(t *testing.T) { c, _ := setupClient(t, nil) - app := fiber.New(fiber.Config{DisableStartupMessage: true}) + app := fiber.New() wantErr := errors.New("denied") var gotAction string - admin.MountCatalog(app, c, admin.WithAuthorizer(func(_ *fiber.Ctx, action string) error { + admin.MountCatalog(app, c, admin.WithAuthorizer(func(_ fiber.Ctx, action string) error { gotAction = action return wantErr })) diff --git a/api_client.go b/api_client.go index 3001aa1..0200c37 100644 --- a/api_client.go +++ b/api_client.go @@ -4,8 +4,8 @@ import ( "context" "time" - "github.com/LerianStudio/lib-observability/log" - internalclient "github.com/LerianStudio/lib-systemplane/internal/client" + "github.com/LerianStudio/lib-observability/v2/log" + internalclient "github.com/LerianStudio/lib-systemplane/v2/internal/client" ) func asInternalClient(c *Client) *internalclient.Client { diff --git a/api_constants.go b/api_constants.go index 9d452a4..7f5bfe7 100644 --- a/api_constants.go +++ b/api_constants.go @@ -1,6 +1,6 @@ package systemplane -import internalclient "github.com/LerianStudio/lib-systemplane/internal/client" +import internalclient "github.com/LerianStudio/lib-systemplane/v2/internal/client" // CatalogVersion identifies the public catalog response contract. const CatalogVersion = internalclient.CatalogVersion diff --git a/api_constructors.go b/api_constructors.go index a8d3660..4ab9971 100644 --- a/api_constructors.go +++ b/api_constructors.go @@ -4,9 +4,9 @@ import ( "database/sql" "time" - "github.com/LerianStudio/lib-observability/log" - "github.com/LerianStudio/lib-observability/tracing" - internalclient "github.com/LerianStudio/lib-systemplane/internal/client" + "github.com/LerianStudio/lib-observability/v2/log" + "github.com/LerianStudio/lib-observability/v2/tracing" + internalclient "github.com/LerianStudio/lib-systemplane/v2/internal/client" "go.mongodb.org/mongo-driver/v2/mongo" ) diff --git a/api_errors.go b/api_errors.go index c201651..9ed12fe 100644 --- a/api_errors.go +++ b/api_errors.go @@ -1,6 +1,6 @@ package systemplane -import internalclient "github.com/LerianStudio/lib-systemplane/internal/client" +import internalclient "github.com/LerianStudio/lib-systemplane/v2/internal/client" // Sentinel errors returned by Client methods. var ( diff --git a/api_testing.go b/api_testing.go index caaeeca..10bdf65 100644 --- a/api_testing.go +++ b/api_testing.go @@ -2,7 +2,7 @@ package systemplane -import internalclient "github.com/LerianStudio/lib-systemplane/internal/client" +import internalclient "github.com/LerianStudio/lib-systemplane/v2/internal/client" // TestStore is the public mirror of the internal store.Store interface, // exposed solely for [NewForTesting]. diff --git a/api_types.go b/api_types.go index ba87699..f970047 100644 --- a/api_types.go +++ b/api_types.go @@ -1,6 +1,6 @@ package systemplane -import internalclient "github.com/LerianStudio/lib-systemplane/internal/client" +import internalclient "github.com/LerianStudio/lib-systemplane/v2/internal/client" // Client is the public runtime-config handle for systemplane. // diff --git a/ddl_test.go b/ddl_test.go index c8c73ec..ecff623 100644 --- a/ddl_test.go +++ b/ddl_test.go @@ -6,7 +6,7 @@ import ( "strings" "testing" - systemplane "github.com/LerianStudio/lib-systemplane" + systemplane "github.com/LerianStudio/lib-systemplane/v2" ) func TestSchemaSQL_NonEmpty(t *testing.T) { diff --git a/docs/PROJECT_RULES.md b/docs/PROJECT_RULES.md index 23b72f6..4d8129e 100644 --- a/docs/PROJECT_RULES.md +++ b/docs/PROJECT_RULES.md @@ -62,7 +62,7 @@ lib-systemplane/ - **Minimum**: Go 1.26.3 - Keep `go.mod` updated with latest stable Go version -- Module path: `github.com/LerianStudio/lib-systemplane` +- Module path: `github.com/LerianStudio/lib-systemplane/v2` ### Build Tags @@ -93,7 +93,7 @@ import ( "go.uber.org/zap" // Internal packages - "github.com/LerianStudio/lib-observability/log" + "github.com/LerianStudio/lib-observability/v2/log" ) ``` @@ -322,16 +322,16 @@ func (c *Client) Connect(ctx context.Context) error { Lerian shared-library ownership is split intentionally: -- `github.com/LerianStudio/lib-commons/v5` — non-observability shared primitives. This repo uses `commons/tenant-manager/core`, `commons/net/http`, and `commons/backoff`. -- `github.com/LerianStudio/lib-observability` — canonical observability stack. This repo uses `log`, `tracing`, and `runtime` for structured logging, telemetry, span helpers, redaction, and panic recovery. -- `github.com/LerianStudio/lib-systemplane` — runtime-mutable configuration. Do not duplicate its functionality in service repositories. +- `github.com/LerianStudio/lib-commons/v6` — non-observability shared primitives. This repo uses `commons/tenant-manager/core`, `commons/net/http`, and `commons/backoff`. +- `github.com/LerianStudio/lib-observability/v2` — canonical observability stack. This repo uses `log`, `tracing`, and `runtime` for structured logging, telemetry, span helpers, redaction, and panic recovery. +- `github.com/LerianStudio/lib-systemplane/v2` — runtime-mutable configuration. Do not duplicate its functionality in service repositories. - `github.com/LerianStudio/lib-streaming` — tenant-scoped event streaming. Do not add it to this repo unless a task explicitly requires streaming integration. Do not reintroduce observability packages from `lib-commons`; they are being removed from that module. New observability code must use `lib-observability`. ### Key Third-Party Dependencies -- `github.com/gofiber/fiber/v2` — HTTP framework for the admin routes +- `github.com/gofiber/fiber/v3` — HTTP framework for the admin routes - `github.com/jackc/pgx/v5` — PostgreSQL driver with LISTEN/NOTIFY support - `go.mongodb.org/mongo-driver/v2` — MongoDB driver with change streams - `github.com/hashicorp/golang-lru/v2` — Bounded LRU for lazy tenant cache diff --git a/examples/manager/main.go b/examples/manager/main.go index 4492099..77359e4 100644 --- a/examples/manager/main.go +++ b/examples/manager/main.go @@ -28,9 +28,9 @@ import ( "syscall" "time" - tmpostgres "github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/postgres" - "github.com/LerianStudio/lib-observability/log" - systemplane "github.com/LerianStudio/lib-systemplane" + tmpostgres "github.com/LerianStudio/lib-commons/v6/commons/tenant-manager/postgres" + "github.com/LerianStudio/lib-observability/v2/log" + systemplane "github.com/LerianStudio/lib-systemplane/v2" ) // tenantEvent is the minimal shape any tenant-lifecycle event source emits. diff --git a/go.mod b/go.mod index b0aac82..6b8d27b 100644 --- a/go.mod +++ b/go.mod @@ -1,12 +1,12 @@ -module github.com/LerianStudio/lib-systemplane +module github.com/LerianStudio/lib-systemplane/v2 go 1.26.3 require ( - github.com/LerianStudio/lib-commons/v5 v5.8.0 - github.com/LerianStudio/lib-observability v1.1.0 + github.com/LerianStudio/lib-commons/v6 v6.0.0 + github.com/LerianStudio/lib-observability/v2 v2.0.0 github.com/bxcodec/dbresolver/v2 v2.2.1 - github.com/gofiber/fiber/v2 v2.52.14 + github.com/gofiber/fiber/v3 v3.4.0 github.com/jackc/pgx/v5 v5.10.0 github.com/testcontainers/testcontainers-go v0.42.0 github.com/testcontainers/testcontainers-go/modules/mongodb v0.42.0 @@ -27,7 +27,6 @@ require ( github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/clipperhouse/uax29/v2 v2.7.0 // indirect github.com/containerd/errdefs v1.0.0 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/log v0.1.0 // indirect @@ -46,6 +45,8 @@ require ( github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.30.3 // indirect + github.com/gofiber/schema v1.8.0 // indirect + github.com/gofiber/utils/v2 v2.1.1 // indirect github.com/golang-migrate/migrate/v4 v4.19.1 // indirect github.com/google/uuid v1.6.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 // indirect @@ -60,7 +61,6 @@ require ( github.com/magiconair/properties v1.8.10 // indirect github.com/mattn/go-colorable v0.1.15 // indirect github.com/mattn/go-isatty v0.0.22 // indirect - github.com/mattn/go-runewidth v0.0.24 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/go-archive v0.2.0 // indirect github.com/moby/moby/api v1.54.2 // indirect @@ -72,6 +72,7 @@ require ( github.com/moby/term v0.5.2 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.1 // indirect + github.com/philhofer/fwd v1.2.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/rabbitmq/amqp091-go v1.12.0 // indirect @@ -82,6 +83,7 @@ require ( github.com/sirupsen/logrus v1.9.4 // indirect github.com/sony/gobreaker v1.0.0 // indirect github.com/stretchr/testify v1.11.1 // indirect + github.com/tinylib/msgp v1.6.4 // indirect github.com/tklauser/go-sysconf v0.4.0 // indirect github.com/tklauser/numcpus v0.12.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect diff --git a/go.sum b/go.sum index 8ecbdda..b0761a5 100644 --- a/go.sum +++ b/go.sum @@ -6,10 +6,10 @@ github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEK github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= -github.com/LerianStudio/lib-commons/v5 v5.8.0 h1:u0AK2HbbP3l4B+MxZOBBmnEF9bk6HHDjq6JYTXKZHyE= -github.com/LerianStudio/lib-commons/v5 v5.8.0/go.mod h1:QFluaXHnCTWzHhVvh568JFoBn64pCH8roeIurBRZNC4= -github.com/LerianStudio/lib-observability v1.1.0 h1:e/OrIoTKo8gI1RKXgKDyDDKcrddR4beh53al5ZmB6vQ= -github.com/LerianStudio/lib-observability v1.1.0/go.mod h1:PBtmXygWXmcsTnyNLBetyYb/OtsWq6WT9fSJvoppeUQ= +github.com/LerianStudio/lib-commons/v6 v6.0.0 h1:XDKyCKdb2h3l0MBwQQNBRuCsiSTjafJfgp/QLMAEzd0= +github.com/LerianStudio/lib-commons/v6 v6.0.0/go.mod h1:bOPZG4oO2xoSE307JJyXKyhmBo7EyQ5g8DEw5fI/ZEg= +github.com/LerianStudio/lib-observability/v2 v2.0.0 h1:B13t2TlLvu9awqMsnJ6d0RWeftUlf1ROBxLB3okSn6c= +github.com/LerianStudio/lib-observability/v2 v2.0.0/go.mod h1:MuHQdrM8twiwewkwSO1TX6/931mI9oTM0NCIVjumPhQ= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/alicebob/miniredis/v2 v2.38.0 h1:nZAzCR+Lj+Vxk4ZXzm2NuKq2O33RXj1XxJ2e2uP9jiw= @@ -28,8 +28,6 @@ github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1x github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJv2v7Vk= -github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= @@ -59,6 +57,8 @@ github.com/ebitengine/purego v0.10.0 h1:QIw4xfpWT6GWTzaW5XEKy3HXoqrJGx1ijYHzTF0/ github.com/ebitengine/purego v0.10.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fxamacker/cbor/v2 v2.9.2 h1:X4Ksno9+x3cz0TZv69ec1hxP/+tymuR8PXQJyDwfh78= +github.com/fxamacker/cbor/v2 v2.9.2/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM= github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -77,8 +77,12 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.30.3 h1:4MU6YkEwx7GbcPJOZxrtbu+QfF3pJLJuaYTeAH0DYy8= github.com/go-playground/validator/v10 v10.30.3/go.mod h1:4Axh7oCNGcoGkqLoE4YWt6n20mcEIsPRlB7vPk3lpyc= -github.com/gofiber/fiber/v2 v2.52.14 h1:Of3L+9qVFaQNwPlcmEdl5IIodHz8BSE0j37R7rWu4pE= -github.com/gofiber/fiber/v2 v2.52.14/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw= +github.com/gofiber/fiber/v3 v3.4.0 h1:F0aND4vwZF7dR7cbvSwFQQEpBU902XHKWxrLsFBkVqw= +github.com/gofiber/fiber/v3 v3.4.0/go.mod h1:nAhJfdxUIJJph2tPWPmqWf8QDIN2iiqQiQf3lENZpdk= +github.com/gofiber/schema v1.8.0 h1:NGsC9toPHmj8Xg4KpznuXBzNmHG6V5YV0tXKpKMcmis= +github.com/gofiber/schema v1.8.0/go.mod h1:lmbXPQ8hvzXSLkdS2DS7pb4kpunC2Roh7Sj3HMjGfzA= +github.com/gofiber/utils/v2 v2.1.1 h1:kGnoGjwEnFW6w0x45W+kLlmMJvqBGkuUA4oMWKn/T/I= +github.com/gofiber/utils/v2 v2.1.1/go.mod h1:DdOgEVwQTi8cou/AKWPqhXOR4fHGRVhA/rEWL3IXG7Q= github.com/golang-migrate/migrate/v4 v4.19.1 h1:OCyb44lFuQfYXYLx1SCxPZQGU7mcaZ7gH9yH4jSFbBA= github.com/golang-migrate/migrate/v4 v4.19.1/go.mod h1:CTcgfjxhaUtsLipnLoQRWCrjYXycRz/g5+RWDuYgPrE= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= @@ -121,8 +125,6 @@ github.com/mattn/go-colorable v0.1.15 h1:+u9SLTRGnXv73cEsnsmoZBom+dMU88B2M0aDcWy github.com/mattn/go-colorable v0.1.15/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4= github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= -github.com/mattn/go-runewidth v0.0.24 h1:cpokDiIn0MGnhdHwuWnJBITySJ20QyNGnY2kR/ay2DU= -github.com/mattn/go-runewidth v0.0.24/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= github.com/mdelapenya/tlscert v0.2.0 h1:7H81W6Z/4weDvZBNOfQte5GpIMo0lGYEeWbkGp5LJHI= github.com/mdelapenya/tlscert v0.2.0/go.mod h1:O4njj3ELLnJjGdkN7M/vIVCpZ+Cf0L6muqOG4tLSl8o= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= @@ -149,6 +151,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= +github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM= +github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -162,6 +166,8 @@ github.com/redis/go-redis/v9 v9.21.0 h1:FPBE4hhbAke+TLmcY3WkpbDffJEomdqPn3HYiqAt github.com/redis/go-redis/v9 v9.21.0/go.mod h1:v/M13XI1PVCDcm01VtPFOADfZtHf8YW3baQf57KlIkA= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/shamaton/msgpack/v3 v3.1.2 h1:d5gWAIyMU4M0WgDjz6IFSCuXJUA2dFwRHBpDclE8CLw= +github.com/shamaton/msgpack/v3 v3.1.2/go.mod h1:DcQG8jrdrQCIxr3HlMYkiXdMhK+KfN2CitkyzsQV4uc= github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/gopsutil/v4 v4.26.4 h1:B4SXVbcwTyrocPHEmWBC4uCYr4Xcu3MK1TXqbprAOWY= @@ -185,6 +191,8 @@ github.com/testcontainers/testcontainers-go/modules/mongodb v0.42.0 h1:jX10Aprgf github.com/testcontainers/testcontainers-go/modules/mongodb v0.42.0/go.mod h1:Ph+xH0hAC6djPFTjPgLa3VmSfE4h82kzVIKxTj3n2o4= github.com/testcontainers/testcontainers-go/modules/postgres v0.42.0 h1:GCbb1ndrF7OTDiIvxXyItaDab4qkzTFJ48LKFdM7EIo= github.com/testcontainers/testcontainers-go/modules/postgres v0.42.0/go.mod h1:IRPBaI8jXdrNfD0e4Zm7Fbcgaz5shKxOQv4axiL09xs= +github.com/tinylib/msgp v1.6.4 h1:mOwYbyYDLPj35mkA2BjjYejgJk9BuHxDdvRnb6v2ZcQ= +github.com/tinylib/msgp v1.6.4/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA= github.com/tklauser/go-sysconf v0.4.0 h1:7H0uAN+7RkwWRaxhYXDLqa5V3LPrJeV8wmD9dRUgPQU= github.com/tklauser/go-sysconf v0.4.0/go.mod h1:8mTNWyog7H+MpKijp4VmKJAd2bbYQ2zuUwkYRbUArPI= github.com/tklauser/numcpus v0.12.0 h1:NR85qdvHA9pFse3x3weVZ0r0ST8R6l5RHbZrlRaqob4= @@ -193,6 +201,8 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.72.0 h1:R7kYdoWhn1ye1fVpP+cDHDJwYm3NkwLliwgzJ/Abg7M= github.com/valyala/fasthttp v1.72.0/go.mod h1:zsbLTYqcpIktdQytlVBwIjY9La5d6bs990nBxWg8efk= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.2.0 h1:bYKF2AEwG5rqd1BumT4gAnvwU/M9nBp2pTSxeZw7Wvs= diff --git a/internal/client/catalog_test.go b/internal/client/catalog_test.go index f78078b..319122d 100644 --- a/internal/client/catalog_test.go +++ b/internal/client/catalog_test.go @@ -10,7 +10,7 @@ import ( "testing" "time" - "github.com/LerianStudio/lib-systemplane/internal/store" + "github.com/LerianStudio/lib-systemplane/v2/internal/store" ) type catalogSpyStore struct { diff --git a/internal/client/client.go b/internal/client/client.go index 3814b61..7194876 100644 --- a/internal/client/client.go +++ b/internal/client/client.go @@ -12,14 +12,14 @@ import ( "go.mongodb.org/mongo-driver/v2/mongo" - "github.com/LerianStudio/lib-observability/log" - "github.com/LerianStudio/lib-observability/runtime" - "github.com/LerianStudio/lib-observability/tracing" - "github.com/LerianStudio/lib-systemplane/internal/debounce" - "github.com/LerianStudio/lib-systemplane/internal/manager" - mongoDB "github.com/LerianStudio/lib-systemplane/internal/mongodb" - "github.com/LerianStudio/lib-systemplane/internal/postgres" - "github.com/LerianStudio/lib-systemplane/internal/store" + "github.com/LerianStudio/lib-observability/v2/log" + "github.com/LerianStudio/lib-observability/v2/runtime" + "github.com/LerianStudio/lib-observability/v2/tracing" + "github.com/LerianStudio/lib-systemplane/v2/internal/debounce" + "github.com/LerianStudio/lib-systemplane/v2/internal/manager" + mongoDB "github.com/LerianStudio/lib-systemplane/v2/internal/mongodb" + "github.com/LerianStudio/lib-systemplane/v2/internal/postgres" + "github.com/LerianStudio/lib-systemplane/v2/internal/store" ) // refreshTimeout bounds Get calls made by the changefeed-driven refresh loop. diff --git a/internal/client/client_telemetry.go b/internal/client/client_telemetry.go index 1b7c830..6d31217 100644 --- a/internal/client/client_telemetry.go +++ b/internal/client/client_telemetry.go @@ -4,7 +4,7 @@ package client import ( "context" - "github.com/LerianStudio/lib-observability/log" + "github.com/LerianStudio/lib-observability/v2/log" ) func (c *Client) logWarn(ctx context.Context, msg string, fields ...log.Field) { diff --git a/internal/client/client_test.go b/internal/client/client_test.go index 2b93ce6..573df72 100644 --- a/internal/client/client_test.go +++ b/internal/client/client_test.go @@ -10,7 +10,7 @@ import ( "testing" "time" - "github.com/LerianStudio/lib-systemplane/internal/store" + "github.com/LerianStudio/lib-systemplane/v2/internal/store" ) // memStore is a minimal in-memory store.Store implementation used to exercise diff --git a/internal/client/client_testing.go b/internal/client/client_testing.go index 53af2f2..229c30e 100644 --- a/internal/client/client_testing.go +++ b/internal/client/client_testing.go @@ -8,7 +8,7 @@ import ( "reflect" "time" - "github.com/LerianStudio/lib-systemplane/internal/store" + "github.com/LerianStudio/lib-systemplane/v2/internal/store" ) // TestStore is the public mirror of the internal store.Store interface, diff --git a/internal/client/errors.go b/internal/client/errors.go index 5868a88..8898cf2 100644 --- a/internal/client/errors.go +++ b/internal/client/errors.go @@ -3,7 +3,7 @@ package client import ( "errors" - "github.com/LerianStudio/lib-systemplane/internal/store" + "github.com/LerianStudio/lib-systemplane/v2/internal/store" ) // Sentinel errors returned by Client methods. diff --git a/internal/client/get.go b/internal/client/get.go index b10981a..7f49d17 100644 --- a/internal/client/get.go +++ b/internal/client/get.go @@ -8,8 +8,8 @@ import ( "sort" "time" - "github.com/LerianStudio/lib-observability/log" - "github.com/LerianStudio/lib-systemplane/internal/manager" + "github.com/LerianStudio/lib-observability/v2/log" + "github.com/LerianStudio/lib-systemplane/v2/internal/manager" ) // ListEntry is a single entry returned by [Client.List]. diff --git a/internal/client/manager_binding.go b/internal/client/manager_binding.go index 543ac6e..a15b43a 100644 --- a/internal/client/manager_binding.go +++ b/internal/client/manager_binding.go @@ -9,7 +9,7 @@ package client import ( "context" - "github.com/LerianStudio/lib-systemplane/internal/manager" + "github.com/LerianStudio/lib-systemplane/v2/internal/manager" ) // BindManager attaches a Manager to the Client. After binding, MT-mode Get diff --git a/internal/client/manager_binding_test.go b/internal/client/manager_binding_test.go index e5728f6..880a2a9 100644 --- a/internal/client/manager_binding_test.go +++ b/internal/client/manager_binding_test.go @@ -7,7 +7,7 @@ import ( "errors" "testing" - "github.com/LerianStudio/lib-systemplane/internal/manager" + "github.com/LerianStudio/lib-systemplane/v2/internal/manager" ) // TestBackwardCompat_MTWithoutManager_OnChangeReturnsErr pins the v1.4.0 diff --git a/internal/client/onchange.go b/internal/client/onchange.go index 36f0edf..1d26aea 100644 --- a/internal/client/onchange.go +++ b/internal/client/onchange.go @@ -5,7 +5,7 @@ import ( "context" "sync" - "github.com/LerianStudio/lib-observability/log" + "github.com/LerianStudio/lib-observability/v2/log" ) // OnChange registers a callback for backend-observed value changes. diff --git a/internal/client/options.go b/internal/client/options.go index 9aa9c55..ccf9e02 100644 --- a/internal/client/options.go +++ b/internal/client/options.go @@ -4,8 +4,8 @@ package client import ( "time" - "github.com/LerianStudio/lib-observability/log" - "github.com/LerianStudio/lib-observability/tracing" + "github.com/LerianStudio/lib-observability/v2/log" + "github.com/LerianStudio/lib-observability/v2/tracing" ) // clientConfig holds the merged configuration applied by Option functions. diff --git a/internal/client/redact.go b/internal/client/redact.go index 2b7f6b5..a2417fe 100644 --- a/internal/client/redact.go +++ b/internal/client/redact.go @@ -1,6 +1,6 @@ package client -import "github.com/LerianStudio/lib-observability/constants" +import "github.com/LerianStudio/lib-observability/v2/constants" // RedactPolicy controls how a key's value is rendered in admin endpoints and logs. type RedactPolicy int diff --git a/internal/client/set.go b/internal/client/set.go index 18545ab..2037320 100644 --- a/internal/client/set.go +++ b/internal/client/set.go @@ -7,7 +7,7 @@ import ( "fmt" "time" - "github.com/LerianStudio/lib-systemplane/internal/store" + "github.com/LerianStudio/lib-systemplane/v2/internal/store" ) // Set writes a new value for (namespace, key). The value is validated against diff --git a/internal/client/testing_facade_test.go b/internal/client/testing_facade_test.go index 41d9efb..2b6c7b2 100644 --- a/internal/client/testing_facade_test.go +++ b/internal/client/testing_facade_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - "github.com/LerianStudio/lib-systemplane/internal/store" + "github.com/LerianStudio/lib-systemplane/v2/internal/store" ) type facadeTestStore struct { diff --git a/internal/debounce/debounce.go b/internal/debounce/debounce.go index ab9a5c8..5672633 100644 --- a/internal/debounce/debounce.go +++ b/internal/debounce/debounce.go @@ -13,8 +13,8 @@ import ( "sync" "time" - "github.com/LerianStudio/lib-observability/log" - "github.com/LerianStudio/lib-observability/runtime" + "github.com/LerianStudio/lib-observability/v2/log" + "github.com/LerianStudio/lib-observability/v2/runtime" ) // Debouncer coalesces rapid submissions for the same key, firing the diff --git a/internal/manager/connector.go b/internal/manager/connector.go index c303268..2989ca7 100644 --- a/internal/manager/connector.go +++ b/internal/manager/connector.go @@ -9,7 +9,7 @@ import ( "context" "fmt" - tmpostgres "github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/postgres" + tmpostgres "github.com/LerianStudio/lib-commons/v6/commons/tenant-manager/postgres" "github.com/bxcodec/dbresolver/v2" ) diff --git a/internal/manager/connector_pgmgr_integration_test.go b/internal/manager/connector_pgmgr_integration_test.go index d9ea337..4d6de8a 100644 --- a/internal/manager/connector_pgmgr_integration_test.go +++ b/internal/manager/connector_pgmgr_integration_test.go @@ -15,7 +15,7 @@ import ( "strings" "testing" - tmpostgres "github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/postgres" + tmpostgres "github.com/LerianStudio/lib-commons/v6/commons/tenant-manager/postgres" "github.com/bxcodec/dbresolver/v2" _ "github.com/jackc/pgx/v5/stdlib" "github.com/testcontainers/testcontainers-go" diff --git a/internal/manager/connector_pgmgr_test.go b/internal/manager/connector_pgmgr_test.go index ed4dcde..1c38201 100644 --- a/internal/manager/connector_pgmgr_test.go +++ b/internal/manager/connector_pgmgr_test.go @@ -29,7 +29,7 @@ import ( "strings" "testing" - tmpostgres "github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/postgres" + tmpostgres "github.com/LerianStudio/lib-commons/v6/commons/tenant-manager/postgres" ) func TestPgMgrConnector_ResolveDB_GetConnectionFails(t *testing.T) { diff --git a/internal/manager/events.go b/internal/manager/events.go index 2d86764..f5f660f 100644 --- a/internal/manager/events.go +++ b/internal/manager/events.go @@ -5,8 +5,8 @@ import ( "encoding/json" "time" - "github.com/LerianStudio/lib-observability/log" - libRuntime "github.com/LerianStudio/lib-observability/runtime" + "github.com/LerianStudio/lib-observability/v2/log" + libRuntime "github.com/LerianStudio/lib-observability/v2/runtime" ) // applyEvent updates the cache and dispatches OnChange callbacks for one diff --git a/internal/manager/get.go b/internal/manager/get.go index 83341ec..dbf922b 100644 --- a/internal/manager/get.go +++ b/internal/manager/get.go @@ -10,7 +10,7 @@ package manager import ( "context" - tmcore "github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/core" + tmcore "github.com/LerianStudio/lib-commons/v6/commons/tenant-manager/core" ) // TenantIDFromContext extracts the tenant ID set by lib-commons tenant-manager diff --git a/internal/manager/goleak_integration_test.go b/internal/manager/goleak_integration_test.go index 56612bc..7d7c66a 100644 --- a/internal/manager/goleak_integration_test.go +++ b/internal/manager/goleak_integration_test.go @@ -11,7 +11,7 @@ import ( "testing" "time" - "github.com/LerianStudio/lib-systemplane/internal/manager" + "github.com/LerianStudio/lib-systemplane/v2/internal/manager" ) func TestIntegration_Manager_OnTenantDeleted_ReleasesGoroutine(t *testing.T) { diff --git a/internal/manager/handle_lifecycle.go b/internal/manager/handle_lifecycle.go index 3b1ad3a..f50afa9 100644 --- a/internal/manager/handle_lifecycle.go +++ b/internal/manager/handle_lifecycle.go @@ -10,8 +10,8 @@ package manager import ( "context" - tmevent "github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/event" - "github.com/LerianStudio/lib-observability/log" + tmevent "github.com/LerianStudio/lib-commons/v6/commons/tenant-manager/event" + "github.com/LerianStudio/lib-observability/v2/log" ) // HandleTenantLifecycle routes a tenant lifecycle event to the matching On* diff --git a/internal/manager/handle_lifecycle_test.go b/internal/manager/handle_lifecycle_test.go index fdf6084..77e34de 100644 --- a/internal/manager/handle_lifecycle_test.go +++ b/internal/manager/handle_lifecycle_test.go @@ -7,8 +7,8 @@ import ( "errors" "testing" - tmevent "github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/event" - "github.com/LerianStudio/lib-observability/log" + tmevent "github.com/LerianStudio/lib-commons/v6/commons/tenant-manager/event" + "github.com/LerianStudio/lib-observability/v2/log" ) // captureLogger records every Log call so tests can assert on emitted diff --git a/internal/manager/internal_test.go b/internal/manager/internal_test.go index 4c6f320..5c807ce 100644 --- a/internal/manager/internal_test.go +++ b/internal/manager/internal_test.go @@ -6,7 +6,7 @@ import ( "context" "testing" - tmcore "github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/core" + tmcore "github.com/LerianStudio/lib-commons/v6/commons/tenant-manager/core" ) func TestTenantIDFromContext_DelegatesToTmcore(t *testing.T) { diff --git a/internal/manager/lifecycle.go b/internal/manager/lifecycle.go index 3fb3847..b248452 100644 --- a/internal/manager/lifecycle.go +++ b/internal/manager/lifecycle.go @@ -9,7 +9,7 @@ import ( "context" "time" - "github.com/LerianStudio/lib-observability/log" + "github.com/LerianStudio/lib-observability/v2/log" ) // OnTenantActivated bootstraps systemplane state for tenantID. diff --git a/internal/manager/listen.go b/internal/manager/listen.go index 5350a9c..aac32bc 100644 --- a/internal/manager/listen.go +++ b/internal/manager/listen.go @@ -23,9 +23,9 @@ import ( "fmt" "time" - "github.com/LerianStudio/lib-commons/v5/commons/backoff" - "github.com/LerianStudio/lib-observability/log" - libRuntime "github.com/LerianStudio/lib-observability/runtime" + "github.com/LerianStudio/lib-commons/v6/commons/backoff" + "github.com/LerianStudio/lib-observability/v2/log" + libRuntime "github.com/LerianStudio/lib-observability/v2/runtime" "github.com/bxcodec/dbresolver/v2" "github.com/jackc/pgx/v5" ) diff --git a/internal/manager/listen_integration_test.go b/internal/manager/listen_integration_test.go index 28cd70a..56d5861 100644 --- a/internal/manager/listen_integration_test.go +++ b/internal/manager/listen_integration_test.go @@ -18,7 +18,7 @@ import ( "testing" "time" - "github.com/LerianStudio/lib-observability/log" + "github.com/LerianStudio/lib-observability/v2/log" "github.com/bxcodec/dbresolver/v2" _ "github.com/jackc/pgx/v5/stdlib" ) diff --git a/internal/manager/logging.go b/internal/manager/logging.go index 350ff23..df01d4a 100644 --- a/internal/manager/logging.go +++ b/internal/manager/logging.go @@ -4,7 +4,7 @@ package manager import ( "context" - "github.com/LerianStudio/lib-observability/log" + "github.com/LerianStudio/lib-observability/v2/log" ) func (m *Manager) logDebug(ctx context.Context, msg string, fields ...log.Field) { diff --git a/internal/manager/manager.go b/internal/manager/manager.go index 4706663..ff0d993 100644 --- a/internal/manager/manager.go +++ b/internal/manager/manager.go @@ -26,9 +26,9 @@ import ( "context" "sync" - tmpostgres "github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/postgres" - "github.com/LerianStudio/lib-observability/log" - "github.com/LerianStudio/lib-observability/tracing" + tmpostgres "github.com/LerianStudio/lib-commons/v6/commons/tenant-manager/postgres" + "github.com/LerianStudio/lib-observability/v2/log" + "github.com/LerianStudio/lib-observability/v2/tracing" ) // MaxEntriesPerTenant is the defensive upper bound on cached entries per tenant. diff --git a/internal/manager/manager_integration_test.go b/internal/manager/manager_integration_test.go index c670851..20c86e3 100644 --- a/internal/manager/manager_integration_test.go +++ b/internal/manager/manager_integration_test.go @@ -12,9 +12,9 @@ import ( "testing" "time" - tmcore "github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/core" - systemplane "github.com/LerianStudio/lib-systemplane" - "github.com/LerianStudio/lib-systemplane/internal/manager" + tmcore "github.com/LerianStudio/lib-commons/v6/commons/tenant-manager/core" + systemplane "github.com/LerianStudio/lib-systemplane/v2" + "github.com/LerianStudio/lib-systemplane/v2/internal/manager" "github.com/bxcodec/dbresolver/v2" _ "github.com/jackc/pgx/v5/stdlib" "github.com/testcontainers/testcontainers-go" diff --git a/internal/manager/manager_test.go b/internal/manager/manager_test.go index 52fd477..9305681 100644 --- a/internal/manager/manager_test.go +++ b/internal/manager/manager_test.go @@ -6,7 +6,7 @@ import ( "context" "testing" - "github.com/LerianStudio/lib-systemplane/internal/manager" + "github.com/LerianStudio/lib-systemplane/v2/internal/manager" ) func TestNew_NilPgMgr_ReturnsNonNilManager(t *testing.T) { diff --git a/internal/manager/metrics.go b/internal/manager/metrics.go index 5c081ff..b7670af 100644 --- a/internal/manager/metrics.go +++ b/internal/manager/metrics.go @@ -16,8 +16,8 @@ import ( "sync" "sync/atomic" - "github.com/LerianStudio/lib-observability/log" - "github.com/LerianStudio/lib-observability/tracing" + "github.com/LerianStudio/lib-observability/v2/log" + "github.com/LerianStudio/lib-observability/v2/tracing" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" ) diff --git a/internal/manager/metrics_helper_test.go b/internal/manager/metrics_helper_test.go index c7a15e1..7a3eb1c 100644 --- a/internal/manager/metrics_helper_test.go +++ b/internal/manager/metrics_helper_test.go @@ -10,7 +10,7 @@ import ( "context" "testing" - "github.com/LerianStudio/lib-observability/tracing" + "github.com/LerianStudio/lib-observability/v2/tracing" sdkmetric "go.opentelemetry.io/otel/sdk/metric" ) diff --git a/internal/manager/metrics_test.go b/internal/manager/metrics_test.go index a01da89..14ab8c9 100644 --- a/internal/manager/metrics_test.go +++ b/internal/manager/metrics_test.go @@ -19,7 +19,7 @@ import ( "sync/atomic" "testing" - "github.com/LerianStudio/lib-observability/log" + "github.com/LerianStudio/lib-observability/v2/log" "go.opentelemetry.io/otel/attribute" sdkmetric "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/sdk/metric/metricdata" diff --git a/internal/manager/warmload.go b/internal/manager/warmload.go index 5993100..a72445b 100644 --- a/internal/manager/warmload.go +++ b/internal/manager/warmload.go @@ -15,7 +15,7 @@ import ( "errors" "fmt" - "github.com/LerianStudio/lib-observability/log" + "github.com/LerianStudio/lib-observability/v2/log" "github.com/bxcodec/dbresolver/v2" "github.com/jackc/pgx/v5/pgconn" ) diff --git a/internal/mongodb/mongodb.go b/internal/mongodb/mongodb.go index 2f8581c..37cd850 100644 --- a/internal/mongodb/mongodb.go +++ b/internal/mongodb/mongodb.go @@ -29,10 +29,10 @@ import ( "sync/atomic" "time" - tmcore "github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/core" - "github.com/LerianStudio/lib-observability/log" - "github.com/LerianStudio/lib-observability/tracing" - "github.com/LerianStudio/lib-systemplane/internal/store" + tmcore "github.com/LerianStudio/lib-commons/v6/commons/tenant-manager/core" + "github.com/LerianStudio/lib-observability/v2/log" + "github.com/LerianStudio/lib-observability/v2/tracing" + "github.com/LerianStudio/lib-systemplane/v2/internal/store" "go.mongodb.org/mongo-driver/v2/bson" "go.mongodb.org/mongo-driver/v2/mongo" "go.mongodb.org/mongo-driver/v2/mongo/options" diff --git a/internal/mongodb/mongodb_changestream.go b/internal/mongodb/mongodb_changestream.go index a1d4674..8a0de48 100644 --- a/internal/mongodb/mongodb_changestream.go +++ b/internal/mongodb/mongodb_changestream.go @@ -12,10 +12,10 @@ import ( "sync" "time" - "github.com/LerianStudio/lib-commons/v5/commons/backoff" - "github.com/LerianStudio/lib-observability/log" - "github.com/LerianStudio/lib-observability/runtime" - "github.com/LerianStudio/lib-systemplane/internal/store" + "github.com/LerianStudio/lib-commons/v6/commons/backoff" + "github.com/LerianStudio/lib-observability/v2/log" + "github.com/LerianStudio/lib-observability/v2/runtime" + "github.com/LerianStudio/lib-systemplane/v2/internal/store" "go.mongodb.org/mongo-driver/v2/bson" "go.mongodb.org/mongo-driver/v2/mongo" "go.mongodb.org/mongo-driver/v2/mongo/options" diff --git a/internal/mongodb/mongodb_changestream_test.go b/internal/mongodb/mongodb_changestream_test.go index 681d9cd..4f9d5e7 100644 --- a/internal/mongodb/mongodb_changestream_test.go +++ b/internal/mongodb/mongodb_changestream_test.go @@ -12,7 +12,7 @@ import ( "testing" "time" - "github.com/LerianStudio/lib-systemplane/internal/store" + "github.com/LerianStudio/lib-systemplane/v2/internal/store" "go.uber.org/goleak" ) diff --git a/internal/mongodb/mongodb_config.go b/internal/mongodb/mongodb_config.go index 04578c0..e81755c 100644 --- a/internal/mongodb/mongodb_config.go +++ b/internal/mongodb/mongodb_config.go @@ -3,7 +3,7 @@ package mongodb import ( "fmt" - "github.com/LerianStudio/lib-systemplane/internal/store" + "github.com/LerianStudio/lib-systemplane/v2/internal/store" "go.opentelemetry.io/otel/trace/noop" ) diff --git a/internal/mongodb/mongodb_crud.go b/internal/mongodb/mongodb_crud.go index 4c5362d..dd249ef 100644 --- a/internal/mongodb/mongodb_crud.go +++ b/internal/mongodb/mongodb_crud.go @@ -5,7 +5,7 @@ import ( "context" "fmt" - "github.com/LerianStudio/lib-systemplane/internal/store" + "github.com/LerianStudio/lib-systemplane/v2/internal/store" "go.mongodb.org/mongo-driver/v2/bson" "go.mongodb.org/mongo-driver/v2/mongo" "go.mongodb.org/mongo-driver/v2/mongo/options" diff --git a/internal/mongodb/mongodb_events.go b/internal/mongodb/mongodb_events.go index 23f931c..8d62cb5 100644 --- a/internal/mongodb/mongodb_events.go +++ b/internal/mongodb/mongodb_events.go @@ -3,8 +3,8 @@ package mongodb import ( "hash/fnv" - "github.com/LerianStudio/lib-observability/runtime" - "github.com/LerianStudio/lib-systemplane/internal/store" + "github.com/LerianStudio/lib-observability/v2/runtime" + "github.com/LerianStudio/lib-systemplane/v2/internal/store" ) // seenEntry records what we already emitted at the current watermark boundary. diff --git a/internal/mongodb/mongodb_goleak_integration_test.go b/internal/mongodb/mongodb_goleak_integration_test.go index 84dffd3..538cadb 100644 --- a/internal/mongodb/mongodb_goleak_integration_test.go +++ b/internal/mongodb/mongodb_goleak_integration_test.go @@ -12,8 +12,8 @@ import ( "testing" "time" - "github.com/LerianStudio/lib-systemplane/internal/mongodb" - "github.com/LerianStudio/lib-systemplane/internal/store" + "github.com/LerianStudio/lib-systemplane/v2/internal/mongodb" + "github.com/LerianStudio/lib-systemplane/v2/internal/store" "go.uber.org/goleak" ) diff --git a/internal/mongodb/mongodb_integration_test.go b/internal/mongodb/mongodb_integration_test.go index c256f5e..365137f 100644 --- a/internal/mongodb/mongodb_integration_test.go +++ b/internal/mongodb/mongodb_integration_test.go @@ -9,10 +9,10 @@ import ( "testing" "time" - tmcore "github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/core" - "github.com/LerianStudio/lib-systemplane/internal/mongodb" - "github.com/LerianStudio/lib-systemplane/internal/store" - "github.com/LerianStudio/lib-systemplane/systemplanetest" + tmcore "github.com/LerianStudio/lib-commons/v6/commons/tenant-manager/core" + "github.com/LerianStudio/lib-systemplane/v2/internal/mongodb" + "github.com/LerianStudio/lib-systemplane/v2/internal/store" + "github.com/LerianStudio/lib-systemplane/v2/systemplanetest" "github.com/testcontainers/testcontainers-go" mongocontainer "github.com/testcontainers/testcontainers-go/modules/mongodb" "go.mongodb.org/mongo-driver/v2/mongo" diff --git a/internal/mongodb/mongodb_polling_integration_test.go b/internal/mongodb/mongodb_polling_integration_test.go index b53d210..590d58e 100644 --- a/internal/mongodb/mongodb_polling_integration_test.go +++ b/internal/mongodb/mongodb_polling_integration_test.go @@ -21,7 +21,7 @@ import ( "testing" "time" - "github.com/LerianStudio/lib-systemplane/internal/store" + "github.com/LerianStudio/lib-systemplane/v2/internal/store" "github.com/testcontainers/testcontainers-go" mongocontainer "github.com/testcontainers/testcontainers-go/modules/mongodb" "go.mongodb.org/mongo-driver/v2/bson" diff --git a/internal/mongodb/mongodb_unit_test.go b/internal/mongodb/mongodb_unit_test.go index 1f233a2..282a94b 100644 --- a/internal/mongodb/mongodb_unit_test.go +++ b/internal/mongodb/mongodb_unit_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - "github.com/LerianStudio/lib-systemplane/internal/store" + "github.com/LerianStudio/lib-systemplane/v2/internal/store" "go.mongodb.org/mongo-driver/v2/mongo" ) diff --git a/internal/postgres/postgres.go b/internal/postgres/postgres.go index c2ce901..472db07 100644 --- a/internal/postgres/postgres.go +++ b/internal/postgres/postgres.go @@ -31,10 +31,10 @@ import ( "sync" "time" - tmcore "github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/core" - "github.com/LerianStudio/lib-observability/log" - "github.com/LerianStudio/lib-observability/tracing" - "github.com/LerianStudio/lib-systemplane/internal/store" + tmcore "github.com/LerianStudio/lib-commons/v6/commons/tenant-manager/core" + "github.com/LerianStudio/lib-observability/v2/log" + "github.com/LerianStudio/lib-observability/v2/tracing" + "github.com/LerianStudio/lib-systemplane/v2/internal/store" "github.com/bxcodec/dbresolver/v2" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" diff --git a/internal/postgres/postgres_config.go b/internal/postgres/postgres_config.go index 19640a9..569d0b5 100644 --- a/internal/postgres/postgres_config.go +++ b/internal/postgres/postgres_config.go @@ -5,7 +5,7 @@ import ( "fmt" "strings" - "github.com/LerianStudio/lib-systemplane/internal/store" + "github.com/LerianStudio/lib-systemplane/v2/internal/store" ) // New creates a Postgres-backed Store. Validates the configuration but does diff --git a/internal/postgres/postgres_goleak_integration_test.go b/internal/postgres/postgres_goleak_integration_test.go index 4615789..cd7e853 100644 --- a/internal/postgres/postgres_goleak_integration_test.go +++ b/internal/postgres/postgres_goleak_integration_test.go @@ -12,8 +12,8 @@ import ( "testing" "time" - "github.com/LerianStudio/lib-systemplane/internal/postgres" - "github.com/LerianStudio/lib-systemplane/internal/store" + "github.com/LerianStudio/lib-systemplane/v2/internal/postgres" + "github.com/LerianStudio/lib-systemplane/v2/internal/store" _ "github.com/jackc/pgx/v5/stdlib" ) diff --git a/internal/postgres/postgres_integration_test.go b/internal/postgres/postgres_integration_test.go index 003e217..e2aeca1 100644 --- a/internal/postgres/postgres_integration_test.go +++ b/internal/postgres/postgres_integration_test.go @@ -12,11 +12,11 @@ import ( "testing" "time" - tmcore "github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/core" - systemplane "github.com/LerianStudio/lib-systemplane" - "github.com/LerianStudio/lib-systemplane/internal/postgres" - "github.com/LerianStudio/lib-systemplane/internal/store" - "github.com/LerianStudio/lib-systemplane/systemplanetest" + tmcore "github.com/LerianStudio/lib-commons/v6/commons/tenant-manager/core" + systemplane "github.com/LerianStudio/lib-systemplane/v2" + "github.com/LerianStudio/lib-systemplane/v2/internal/postgres" + "github.com/LerianStudio/lib-systemplane/v2/internal/store" + "github.com/LerianStudio/lib-systemplane/v2/systemplanetest" "github.com/bxcodec/dbresolver/v2" _ "github.com/jackc/pgx/v5/stdlib" "github.com/testcontainers/testcontainers-go" diff --git a/internal/postgres/postgres_listen.go b/internal/postgres/postgres_listen.go index 7ccdd3c..e4a942c 100644 --- a/internal/postgres/postgres_listen.go +++ b/internal/postgres/postgres_listen.go @@ -12,10 +12,10 @@ import ( "sync" "time" - "github.com/LerianStudio/lib-commons/v5/commons/backoff" - "github.com/LerianStudio/lib-observability/log" - "github.com/LerianStudio/lib-observability/runtime" - "github.com/LerianStudio/lib-systemplane/internal/store" + "github.com/LerianStudio/lib-commons/v6/commons/backoff" + "github.com/LerianStudio/lib-observability/v2/log" + "github.com/LerianStudio/lib-observability/v2/runtime" + "github.com/LerianStudio/lib-systemplane/v2/internal/store" "github.com/jackc/pgx/v5" ) diff --git a/internal/postgres/postgres_listen_test.go b/internal/postgres/postgres_listen_test.go index 4e59fdf..efede02 100644 --- a/internal/postgres/postgres_listen_test.go +++ b/internal/postgres/postgres_listen_test.go @@ -13,7 +13,7 @@ import ( "testing" "time" - "github.com/LerianStudio/lib-systemplane/internal/store" + "github.com/LerianStudio/lib-systemplane/v2/internal/store" "go.uber.org/goleak" ) diff --git a/internal/postgres/postgres_notify.go b/internal/postgres/postgres_notify.go index 470c817..a05fec0 100644 --- a/internal/postgres/postgres_notify.go +++ b/internal/postgres/postgres_notify.go @@ -3,8 +3,8 @@ package postgres import ( "encoding/json" - "github.com/LerianStudio/lib-observability/runtime" - "github.com/LerianStudio/lib-systemplane/internal/store" + "github.com/LerianStudio/lib-observability/v2/runtime" + "github.com/LerianStudio/lib-systemplane/v2/internal/store" ) func (s *Store) dispatchEvent(evt store.Event) { diff --git a/internal/postgres/postgres_unit_test.go b/internal/postgres/postgres_unit_test.go index dcfe9de..80fb054 100644 --- a/internal/postgres/postgres_unit_test.go +++ b/internal/postgres/postgres_unit_test.go @@ -9,7 +9,7 @@ import ( "strings" "testing" - "github.com/LerianStudio/lib-systemplane/internal/store" + "github.com/LerianStudio/lib-systemplane/v2/internal/store" ) func TestNew_ConfigValidationAndDefaults(t *testing.T) { diff --git a/manager.go b/manager.go index 8d13c0a..7e38a30 100644 --- a/manager.go +++ b/manager.go @@ -12,11 +12,11 @@ package systemplane import ( - tmpostgres "github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/postgres" - "github.com/LerianStudio/lib-observability/log" - "github.com/LerianStudio/lib-observability/tracing" - internalclient "github.com/LerianStudio/lib-systemplane/internal/client" - internalmanager "github.com/LerianStudio/lib-systemplane/internal/manager" + tmpostgres "github.com/LerianStudio/lib-commons/v6/commons/tenant-manager/postgres" + "github.com/LerianStudio/lib-observability/v2/log" + "github.com/LerianStudio/lib-observability/v2/tracing" + internalclient "github.com/LerianStudio/lib-systemplane/v2/internal/client" + internalmanager "github.com/LerianStudio/lib-systemplane/v2/internal/manager" ) // Manager owns per-tenant cache + push hot-reload bookkeeping for MT diff --git a/manager_methods.go b/manager_methods.go index 71beb13..17bf045 100644 --- a/manager_methods.go +++ b/manager_methods.go @@ -7,7 +7,7 @@ package systemplane import ( "context" - tmevent "github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/event" + tmevent "github.com/LerianStudio/lib-commons/v6/commons/tenant-manager/event" ) // OnTenantActivated bootstraps systemplane state for tenantID: @@ -87,7 +87,7 @@ func (m *Manager) IsClosed() bool { // must never wedge the consumer's lifecycle dispatch pipeline. // // The signature is intentionally identical to -// github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/event.EventHandler +// github.com/LerianStudio/lib-commons/v6/commons/tenant-manager/event.EventHandler // so a bound Manager can be registered directly as an event handler. // // Nil-receiver safe: calling on a nil Manager is a no-op returning nil. diff --git a/manager_methods_test.go b/manager_methods_test.go index a1a3013..1806c9b 100644 --- a/manager_methods_test.go +++ b/manager_methods_test.go @@ -6,8 +6,8 @@ import ( "context" "testing" - tmevent "github.com/LerianStudio/lib-commons/v5/commons/tenant-manager/event" - systemplane "github.com/LerianStudio/lib-systemplane" + tmevent "github.com/LerianStudio/lib-commons/v6/commons/tenant-manager/event" + systemplane "github.com/LerianStudio/lib-systemplane/v2" ) // These tests exercise the public HandleTenantLifecycle proxy. Routing diff --git a/systemplanetest/contract.go b/systemplanetest/contract.go index 576fb72..8fcb949 100644 --- a/systemplanetest/contract.go +++ b/systemplanetest/contract.go @@ -14,7 +14,7 @@ import ( "testing" "time" - "github.com/LerianStudio/lib-systemplane/internal/store" + "github.com/LerianStudio/lib-systemplane/v2/internal/store" ) // Factory constructs a fresh Store for one test. Backends embed test-fixture From a2feb595d2701f44fb7fe64a841abde19b0a9285 Mon Sep 17 00:00:00 2001 From: Fred Amaral Date: Tue, 21 Jul 2026 19:56:21 -0300 Subject: [PATCH 2/2] docs(docs): drop LISTEN from multi-tenant role Multi-tenant mode disables LISTEN/NOTIFY; the runtime role needs DML only. Removes a contradictory privilege from the guidance (CodeRabbit review). X-Lerian-Ref: 0x1 Claude-Session: https://claude.ai/code/session_019CPR8BaUFL4TuPVos9DGds --- CLAUDE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index f43164e..3b1e5ef 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -58,7 +58,7 @@ These are external module imports. Do not rewrite them to in-repo paths. Do not The Client runs in one of two modes selected at construction: - **Single-tenant** (default). The constructor receives a non-nil `*sql.DB` / `*mongo.Client`. Reads serve from an in-process cache; writes upsert through the store and update the cache. The backend's changefeed (LISTEN/NOTIFY on Postgres, change stream on MongoDB) drives invalidation and fires `OnChange` subscribers. -- **Multi-tenant** (opt-in via `WithMultiTenantEnabled()`). DB/client may be nil. Every read/write resolves the tenant database from `ctx` via `tmcore.GetPGContext(ctx, module)` / `tmcore.GetMBContext(ctx, module)` (`lib-commons/v6/commons/tenant-manager/core`). For Postgres the lib performs NO runtime schema provisioning — `systemplane_entries` plus its NOTIFY trigger function/triggers must be created externally via `SchemaSQL()` / `DefaultSeedSQL()` (e.g. the consumer's migration pipeline); the runtime role only needs DML + `LISTEN`. (MongoDB still bootstraps its collection/indexes lazily once per resolved tenant database via a `sync.Map`-backed `sync.Once` cache.) No in-process cache. No LISTEN/NOTIFY. `OnChange` returns `ErrNotSupportedInMultiTenant`. Callers wire `tenant-manager/middleware.TenantMiddleware` (with `WithPG(...)` or `WithMB(...)` and a matching module name) before the lib's handlers. +- **Multi-tenant** (opt-in via `WithMultiTenantEnabled()`). DB/client may be nil. Every read/write resolves the tenant database from `ctx` via `tmcore.GetPGContext(ctx, module)` / `tmcore.GetMBContext(ctx, module)` (`lib-commons/v6/commons/tenant-manager/core`). For Postgres the lib performs NO runtime schema provisioning — `systemplane_entries` plus its NOTIFY trigger function/triggers must be created externally via `SchemaSQL()` / `DefaultSeedSQL()` (e.g. the consumer's migration pipeline); the runtime role only needs DML. (MongoDB still bootstraps its collection/indexes lazily once per resolved tenant database via a `sync.Map`-backed `sync.Once` cache.) No in-process cache. No LISTEN/NOTIFY. `OnChange` returns `ErrNotSupportedInMultiTenant`. Callers wire `tenant-manager/middleware.TenantMiddleware` (with `WithPG(...)` or `WithMB(...)` and a matching module name) before the lib's handlers. ### Storage shape