packagecompat

package
v4.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 11, 2026 License: MIT Imports: 47 Imported by: 0

Documentation

Overview

Package packagecompat compares a route's legacy kernel handler with its package-native implementation on identical seeded data. Extraction PRs use it to prove that a native route answers byte-compatibly (after v2compat.NormalizeForCompare) before its mode moves past shadow.

Every run seeds two independent databases: the legacy handler reads the kernel's global database, the native handler gets its own connection. They are SQLite files by default; with ANIX_TEST_POSTGRES_DSN set, RunRead and RunWrite also run on two PostgreSQL schemas. Each case starts from empty databases with the route's Models migrated; the cases a test runs share the migrated databases, emptied between cases (shared.go).

Index

Constants

View Source
const PostgresDSNEnvironment = "ANIX_TEST_POSTGRES_DSN"

PostgresDSNEnvironment enables the PostgreSQL runs.

Variables

This section is empty.

Functions

func CompareAnswers

func CompareAnswers(legacy, native Result) error

CompareAnswers reports how two answers differ: status code, or body after v2compat.NormalizeForCompare. A sealed handle in the native answer matches the secret the legacy answer shows there, as in the router's shadow comparison (v2compat.EqualForCompare).

func FinalizeNodeSplit added in v4.2.0

func FinalizeNodeSplit(t testing.TB, db *gorm.DB, tables ...string)

FinalizeNodeSplit takes tables (all split tables when none are named) through the split as an operator does (docs/UPGRADE.md): the state rows, a backfill, a matching verification, dual_read, then finalize. Their legacy secret columns then hold tombstones and redacted documents, and the kernel creates the views that wait for finalize (packagestore.EnsureKernelAPIViews). Seed functions call it after the rows are written, on both sides.

func ForEachKernelDatabase added in v4.2.0

func ForEachKernelDatabase(t *testing.T, models []any, body func(t *testing.T, db *gorm.DB))

ForEachKernelDatabase runs body on a fresh kernel database with models migrated, on SQLite and, with ANIX_TEST_POSTGRES_DSN set, on a throwaway PostgreSQL schema; the database is also the kernel's global one, which the legacy handlers and the kernel's services read. A test whose legacy and native sides must share live state (agent sessions the kernel holds in memory) runs both on it.

func KernelSettings

func KernelSettings(t testing.TB, db *gorm.DB, grants SettingsGrants) kernelsettingsv1.KernelSettingsClient

KernelSettings serves the kernel's KernelSettings (internal/kernelsettings) on db in process over gRPC, to grants' host, and returns a client for it, as the package host gets one over its bridge connection.

func Lease added in v4.2.0

func Lease(db *gorm.DB, packageID string) func(ctx context.Context, name string) bool

Lease answers what the kernel's storage lease grants the package whose manifest template is packages/<packageID>/manifest.template.json on db, as the kernel decides it when a host asks (service.EffectiveStorageGrants): an adoption of v2_node, v2_node_protocol or v2_forward_node, and a view of the split's remainder, only once finalized. The answer is computed when asked, so it sees what the case's seed did. It is a native service's Leased.

func NodeSplitModels added in v4.2.0

func NodeSplitModels() []any

NodeSplitModels are the node credential split's tables, and the operation log its phase changes are audited in. A route on a table or view of the split's remainder (docs/architecture/node-ops-service.md section 4.6) lists them in Route.Models, so the shared databases keep them between cases.

func OpenSQLite added in v4.2.0

func OpenSQLite(t *testing.T, models ...any) *gorm.DB

OpenSQLite is a fresh SQLite kernel database with models migrated, for a test that calls a native handler directly.

func RequireSame added in v4.2.0

func RequireSame(t *testing.T, c Case, legacy, native Result)

RequireSame requires two answers to be the same, as RunRead does: the headers c lists sent by both, the status and the normalized body equal once c's masked paths are masked.

func RunKernelRead added in v4.2.0

func RunKernelRead(t *testing.T, route KernelRoute, c Case)

RunKernelRead is RunRead for a KernelRoute. Unless the case expects the route to fall back (Case.Fallback), the native handler must answer itself: an answer the host relayed to the kernel's legacy handler would match by construction.

func RunKernelWrite added in v4.2.0

func RunKernelWrite(t *testing.T, route KernelRoute, c Case)

RunKernelWrite is RunWrite for a KernelRoute.

func RunRead

func RunRead(t *testing.T, route Route, c Case)

RunRead runs c against both implementations and requires equal status codes and normalized bodies.

func RunWrite

func RunWrite(t *testing.T, route Route, c Case)

RunWrite is RunRead plus an equal Snapshot of each database afterwards.

Types

type Case

type Case struct {
	Name string
	// Path is the concrete request path, with query string if any.
	Path      string
	Body      []byte
	Principal pluginhostsdk.Principal
	// Seed writes the same data into each database.
	Seed func(t testing.TB, db *gorm.DB)
	// Snapshot returns the database state RunWrite compares after the
	// request; any JSON-encodable value.
	Snapshot func(t testing.TB, db *gorm.DB) any
	// Mask lists dotted JSON paths (for example "data.token") whose values
	// differ by design, such as tokens and secrets: they must exist on both
	// sides and are replaced before comparing.
	Mask []string
	// Headers lists response headers both sides must send.
	Headers []string
	// RequestHeaders are sent with the request: the legacy handler reads
	// them from it, the native one from the metadata the kernel forwards.
	RequestHeaders map[string]string
	// Host is the request's Host (default example.com) and TLS whether it
	// arrived over TLS: the legacy handler reads them from the request, the
	// native one from the request scheme and host the kernel sends.
	Host string
	TLS  bool
	// Warmup bodies are sent, in order, before the compared request.
	Warmup [][]byte
	// Fallback is set when the native side must answer from the legacy
	// handler (RunKernelRead, RunKernelWrite): the route cannot serve the
	// request natively, for example before the node credential split is
	// finalized.
	Fallback bool
}

Case is one request.

type Kernel added in v4.2.0

type Kernel struct {
	// contains filtered or unexported fields
}

Kernel is the native side of a KernelRoute: the gateway, one package host and the KernelNodeOps engine.

func StartKernel added in v4.2.0

func StartKernel(t testing.TB, opts KernelOptions) *Kernel

StartKernel starts the kernel's side of a package: a KernelNodeOps engine on opts.DB with the executors a kernel registers (agent ones on opts.Agents), the gateway with the kernel's node secret fields, and the package host on a real bridge session, every route native.

func (*Kernel) Do added in v4.2.0

func (k *Kernel) Do(t testing.TB, method, path string, body []byte, headers map[string]string) Result

Do sends one request through the gateway, without a Case: method, path, body and request headers, as the administrator (actor 1).

func (*Kernel) LegacyCalls added in v4.2.0

func (k *Kernel) LegacyCalls(routeID string) int

LegacyCalls counts the requests of a route the host relayed to the kernel's legacy handler.

func (*Kernel) PendingHandles added in v4.2.0

func (k *Kernel) PendingHandles() int

PendingHandles counts the sealed handles still held: none once every request ended.

func (*Kernel) Received added in v4.2.0

func (k *Kernel) Received(routeID string) []pluginhostsdk.NativeRequest

Received returns what the package's native handler of a route was sent.

func (*Kernel) Serve added in v4.2.0

func (k *Kernel) Serve(t *testing.T, method, pattern string, c Case) Result

Serve sends c through the gateway, as the principal of c.

type KernelHostRoute added in v4.2.0

type KernelHostRoute struct {
	Method, Pattern, RouteID string
	// Legacy is the kernel's handler, which the host relays to.
	Legacy gin.HandlerFunc
	// Native builds the package's handler with the host's KernelNodeOps
	// client.
	Native func(nodeOps kernelnodeopsv1.KernelNodeOpsClient) pluginhostsdk.NativeHandler
}

KernelHostRoute is one route of a KernelOptions host.

type KernelOptions added in v4.2.0

type KernelOptions struct {
	// DB is the kernel database the engine records in.
	DB        *gorm.DB
	PackageID string
	// Capabilities are the KernelNodeOps capabilities the package holds.
	Capabilities []string
	// Agents are the agent sessions the executors and session RPCs read.
	Agents kernelnodeops.SourcesFunc
	// Routes are the package's routes, each in native mode.
	Routes []KernelHostRoute
}

KernelOptions configure StartKernel.

type KernelRoute added in v4.2.0

type KernelRoute struct {
	Route
	// PackageID is the route's package.
	PackageID string
	// Capabilities are the KernelNodeOps capabilities the package's signed
	// release declares (kernel.nodeops.<family>.v1).
	Capabilities []string
	// NativeService builds the package's native handler on the native
	// database, with the host's KernelNodeOps client.
	NativeService func(db *gorm.DB, nodeOps kernelnodeopsv1.KernelNodeOpsClient) pluginhostsdk.NativeHandler
	// Agents are the agent sessions the kernel's executors and session RPCs
	// read; nil reads none.
	Agents kernelnodeops.SourcesFunc
}

KernelRoute is a route whose native side runs the whole path a deployment runs: the kernel's v2 gateway (which seals the node secrets of the routes in config/node-secret-fields.json into handles and expands the handles an answer shows), a real package bridge session serving KernelNodeOps, the SDK router with the route in native mode, and the kernel's KernelNodeOps engine with its executors on the native database (docs/architecture/node-ops-service.md). The package host never sees a node secret, as in a deployment.

type Result

type Result struct {
	StatusCode int
	Body       []byte
	Header     http.Header
	State      any
}

Result is one side's answer.

func ServeLegacy added in v4.2.0

func ServeLegacy(t *testing.T, method, pattern string, c Case, legacy gin.HandlerFunc) Result

ServeLegacy sends c to the kernel's legacy handler, as the principal of c, for a test that runs both sides on one database (ForEachKernelDatabase).

type Route

type Route struct {
	// Method and Pattern are the gin registration, for example GET and
	// "/api/v2/user/knowledge/:id".
	Method  string
	Pattern string
	RouteID string
	// Legacy is the kernel's gin handler. It reads database.GetDB().
	Legacy gin.HandlerFunc
	// Native builds the package implementation on a database connection.
	Native func(db *gorm.DB) pluginhostsdk.NativeHandler
	// Models are migrated into both databases before Seed runs.
	Models []any
}

Route is one v2 route with both implementations.

type SettingsGrants

type SettingsGrants struct {
	Host         packagebridge.HostIdentity
	Capabilities []string
}

SettingsGrants authorizes the capabilities a package's signed release declares, for that package's host only.

func (SettingsGrants) AuthorizeCapability

func (g SettingsGrants) AuthorizeCapability(_ context.Context, host packagebridge.HostIdentity, capability string) error

AuthorizeCapability implements kernelsettings.Authorizer.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL