apply

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Jun 16, 2026 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package apply provides the structured-write-operation primitive and the fail-closed tenant gate that audits its application against storage.

History (2026-05-12): this package was lifted from pkg/replication/ when A8.1 (Option B) deleted the standalone replication library. The receiver/socket machinery did not survive the deletion — that infrastructure was NNG/TCP-shaped fossilization with no `cmd/server`-native rebuild path. What did survive is what this package contains: the WriteOperation wire-format struct, the WriteExecutor abstraction, and ApplyWriteOperation — the fail-closed apply gate that A8 (the parent audit) added to refuse empty TenantID. Those primitives are still load-bearing for the audit-regression suite and would be re-derived from scratch by any future cmd/server-native replication rebuild.

See:

  • docs/A8_REPLICATION_TENANCY_DESIGN.md §Q1 (TenantID on the wire).
  • docs/A8_1_SPIKE_2026-05-12.md §6 (Decision B).
  • pkg/api/audit_regression_test.go A8 row (drives ApplyWriteOperation end-to-end against a real *storage.GraphStorage).

Index

Constants

View Source
const AllowEmptyTenantEnv = "REPLICATION_ALLOW_EMPTY_TENANT"

AllowEmptyTenantEnv opts a deployment out of the default fail-closed behavior on empty WriteOperation.TenantID. See doc on ApplyWriteOperation — same shape as the JWT_SECRET fail-closed pattern in pkg/api/server_init.go.

Variables

This section is empty.

Functions

func ApplyWriteOperation

func ApplyWriteOperation(executor WriteExecutor, op WriteOperation) error

ApplyWriteOperation applies a single WriteOperation against executor, with a fail-closed gate on empty TenantID.

Audit A8 (2026-05-09): empty op.TenantID is refused by default — silent default-tenant routing is the exact pattern this audit closes (in-house precedent: the JWT_SECRET fail-closed fix in pkg/api/server_init.go:74-77).

The AllowEmptyTenantEnv=1 env var opts back into the legacy behavior (default empty to "default") for one-shot migration scenarios — e.g., draining writes from an unmigrated sender. Off by default; document and remove once all senders populate TenantID.

op is taken by value so the escape-hatch's TenantID rewrite never mutates caller state. Callers can reuse a single op struct across multiple apply calls without surprise.

Returns nil on successful dispatch AND on fail-closed refusal — refusal is the documented success path of the gate, signaled by the log.Printf above. A non-nil return means the executor itself rejected the op (e.g., storage error); callers driving the apply path from tests should treat a non-nil return as a fatal signal rather than relying on observable-state assertions alone.

Types

type WriteExecutor

type WriteExecutor interface {
	CreateNodeWithTenant(tenantID string, labels []string, properties map[string]interface{}) (uint64, error)
	CreateEdgeWithTenant(tenantID string, from, to uint64, edgeType string, properties map[string]interface{}, weight float64) (uint64, error)
}

WriteExecutor is the storage-write surface ApplyWriteOperation requires. interface{} for properties keeps the abstraction decoupled from storage.Value's concrete shape — the audit-regression suite's adapter converts at the boundary.

Audit A8 (2026-05-09): methods carry an explicit tenantID. The caller (ApplyWriteOperation) refuses empty tenantID by default — see the fail-closed gate there. Concrete implementers can assume tenantID is non-empty unless the AllowEmptyTenantEnv escape hatch is set (in which case the apply path defaults it to "default" before calling these methods).

type WriteOperation

type WriteOperation struct {
	TenantID   string                 `json:"tenant_id"`
	Type       string                 `json:"type"` // "create_node", "create_edge"
	Labels     []string               `json:"labels,omitempty"`
	Properties map[string]interface{} `json:"properties,omitempty"`
	FromNodeID uint64                 `json:"from_node_id,omitempty"`
	ToNodeID   uint64                 `json:"to_node_id,omitempty"`
	EdgeType   string                 `json:"edge_type,omitempty"`
	Weight     float64                `json:"weight,omitempty"`
}

WriteOperation is a structured representation of a graph mutation in transit between a write-source and a write-applier. JSON-serializable; tenant-required on the wire.

Audit A8 (2026-05-09): TenantID is required on every WriteOperation. The apply path (ApplyWriteOperation) fails closed when TenantID is empty — silently defaulting to the default tenant on the wire was the exact silent-default class A8 closes (in-house precedent: the JWT_SECRET fail-closed fix in pkg/api/server_init.go). The JSON tag deliberately omits `omitempty` so an explicit empty value reaches the receiver unmodified, which the apply path can log and refuse — rather than appearing identical to a missing field.

Jump to

Keyboard shortcuts

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