provadapter

package
v0.0.21 Latest Latest
Warning

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

Go to latest
Published: Oct 18, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package provadapter is Pasture's thin low-level adapter over the released Provenance global-journal surface (github.com/dayvidpham/provenance at dayvidpham/provenance#4/#5/#6, module pinned to main@ecc7663). It owns exactly the boundary conversions and system-actor activation that pasture#14 places between the portable protocol identity domain (pkg/protocol/portable, produced by the in-memory compiler internal/codegen/ir) and Provenance's durable identity, authority, and command-digest domains.

Scope boundary (pasture#14). This package deliberately does NOT define any pasture.* material event, effect-to-command mapping, task-closure policy, task backend semantics, timeline projection, or public CLI vocabulary — those are pasture#43, the exclusive consumer of this adapter. Everything here is a pure, side-effect-free conversion or a single-purpose registry activation against a real Provenance store; there is no split audit-store write path.

The four capabilities delivered here, each independently testable against a real Provenance store (OpenMemory / a temp-file tracker):

  • refs.go: validated, round-tripping conversions between the portable AssignmentRef/TaskRef/RoleID/MutationRef/AgentRef domain and Provenance's AssignmentID/TaskID/AssignmentSlotID/OperationID/ActorID domains, rejecting wrong or empty domains without making the dependency-free portable package depend on Provenance.
  • authority.go: derivation of a non-aliasing Provenance OperationAuthorityID from a portable bootstrap-agent or assignment authority, preserving authority kind/slot/task so two authorities of the SAME actor over different assignment kinds/slots/tasks can never alias to one key; plus the retained-initiating-identity -> historical ActorID resolution used for committed replay/lookup (never re-resolving whichever assignment is current).
  • digest.go: byte-preserving conversion of a #43-produced ir.CanonicalCommandDigest to the raw Provenance command-digest bytes handed to LookupCommitted and Apply, with no re-canonicalization and no caller digest flag.
  • actors.go: activation of the reserved pasture-system actor namespace (ordinals 0..1023, manifest-v1 ordinal zero seeded as pasture-system/default / software_agent) over a real Provenance actor-namespace registry, with the fixed big-endian ordinal-UUID wire encoding.
  • facade.go: the thin Apply/LookupCommitted facade over the single Provenance journal write path (no split audit store), routing every call through the ref/authority/digest conversions above and surfacing the closed Absent/Committed/Conflict outcome with the underlying typed provenance error round-tripped for errors.Is/As.
  • migrate.go: the finite serial legacy-baseline migration coordinator over MigrateLegacyBaseline — deterministic (RecordedAt, LegacyRowID) ordering, read-only source byte-hash integrity before and after, whole-batch stop-on-first-failure with typed errors round-tripped, and idempotent re-run counts surfaced.
  • legacyaudit.go: the separately-named, read-only 'pasture legacy-audit event list' API over NON-TASK legacy rows, preserving raw actor text, contexts, and source identity verbatim in deterministic order — the surface #43's CLI wires (no CLI wiring here).

Index

Constants

View Source
const (
	// PastureSystemNamespace is the reserved namespace claimed at activation.
	PastureSystemNamespace = "pasture-system"
	// PastureSystemDefaultName is manifest-v1 ordinal zero's registered name.
	PastureSystemDefaultName = "pasture-system/default"
	// PastureSystemReservedOrdinals is the count of reserved ordinals (0..1023).
	PastureSystemReservedOrdinals = 1024
)

Variables

View Source
var ErrSourceMutatedDuringMigration = errors.New("provadapter: legacy source mutated during migration")

ErrSourceMutatedDuringMigration is the sentinel the coordinator raises when the external source's bytes changed across the migration, violating the read-only extraction invariant (§13). It is distinct from any Provenance migration sentinel so a caller can tell an integrity breach from a domain rejection.

View Source
var PastureSystemRange = provenance.UUIDRange{
	Min: [16]byte{},
	Max: provenance.BigEndianUUID(pastureSystemMaxOrdinal),
}

PastureSystemRange is the inclusive [0, 1023] fixed-UUID range the pasture-system namespace claims: Min is the all-zero UUID (ordinal 0) and Max is ordinal 1023 as a 16-byte big-endian value.

Functions

func ActorIDFromAgentRef

func ActorIDFromAgentRef(agent portable.AgentRef) (provenance.ActorID, error)

ActorIDFromAgentRef converts a portable bootstrap AgentRef to a Provenance ActorID. The AgentRef's spelling must be a valid "namespace/uuid" wire form. This is the one-directional bootstrap-actor resolution the authority and continuation paths reuse; there is no reverse ActorID -> AgentRef helper because a live ActorID is not, by itself, a portable bootstrap-agent identity.

func AssignmentAuthorityID

func AssignmentAuthorityID(assignment portable.AssignmentRef, slot portable.RoleID, task portable.TaskRef) (provenance.OperationAuthorityID, error)

AssignmentAuthorityID derives the non-aliasing OperationAuthorityID for a portable assignment authority, preserving the assignment episode identity, its responsibility slot, and its task. Two authorities of the same actor over a different slot, a different task, or a different (predecessor/successor) assignment yield distinct keys and therefore cannot alias.

func AssignmentIDFromRef

func AssignmentIDFromRef(ref portable.AssignmentRef) (provenance.AssignmentID, error)

AssignmentIDFromRef converts a portable AssignmentRef to a Provenance AssignmentID (the opaque, transition-invariant responsibility-episode identity).

func AssignmentRefFromID

func AssignmentRefFromID(id provenance.AssignmentID) (portable.AssignmentRef, error)

AssignmentRefFromID converts a Provenance AssignmentID back to a portable AssignmentRef. It round-trips exactly with AssignmentIDFromRef.

func BootstrapAuthorityID

func BootstrapAuthorityID(agent portable.AgentRef) (provenance.OperationAuthorityID, error)

BootstrapAuthorityID derives the non-aliasing OperationAuthorityID for a portable bootstrap-agent authority (the genesis/system root an operation executes under). It shares no key space with any assignment authority.

func CommandDigestBytes

func CommandDigestBytes(d ir.CanonicalCommandDigest) ([]byte, error)

CommandDigestBytes returns the raw Provenance command-digest bytes for a #43-produced ir.CanonicalCommandDigest, byte-for-byte preserving the digest #43 computed. The result is the exact input to Journal.Apply's OperationInput.CommandDigest and to the LookupCommitted lookup key. A zero/invalid digest is rejected: an empty digest must never stand in for a missing resolved command.

func HistoricalActorID

func HistoricalActorID(
	c ir.MutationContinuation,
	resolveAssignment func(portable.AssignmentRef) (provenance.ActorID, error),
) (provenance.ActorID, error)

HistoricalActorID resolves a completed MutationContinuation's retained initiating identity to the historical ActorID used for its committed replay/lookup. It uses the identity the continuation RETAINED at initiation and never re-resolves whichever assignment happens to be current later: a bootstrap continuation resolves its retained AgentRef directly; an assignment continuation resolves its retained AssignmentRef through the caller-supplied resolveAssignment (the historical-occupant lookup), which #43 backs with a point-in-time store query keyed on the retained ref — not the live owner.

func MutationRefFromID

func MutationRefFromID(op provenance.OperationID) (portable.MutationRef, error)

MutationRefFromID converts a Provenance OperationID back to a portable MutationRef. It round-trips exactly with OperationIDFromRef.

func OperationIDFromRef

func OperationIDFromRef(ref portable.MutationRef) (provenance.OperationID, error)

OperationIDFromRef converts a portable MutationRef to a Provenance OperationID (the caller-supplied idempotency alternate key). The MutationRef identifies one logical stateful invocation across retries; a stable ref maps to a stable OperationID, which is exactly what Apply's replay short-circuit keys on.

func OrdinalActorID

func OrdinalActorID(ordinal uint64) (provenance.ActorID, error)

OrdinalActorID returns the fixed pasture-system ActorID for a reserved ordinal in [0, 1023]. The UUID is the ordinal rendered big-endian into 16 bytes with no version/variant bits, so ordinal zero is the all-zero (uuid.Nil) UUID. An ordinal at or beyond 1024 is rejected: it lies outside the claimed range.

func PastureSystemClaim

func PastureSystemClaim() provenance.ActorNamespaceClaim

PastureSystemClaim is the exact ActorNamespaceClaim activation registers. Its fields are fixed, so an exact re-activation is idempotent and any drift in a stored claim of the same namespace is detectable field-by-field.

func PastureSystemDefaultActorID

func PastureSystemDefaultActorID() provenance.ActorID

PastureSystemDefaultActorID is manifest-v1 ordinal zero: the all-zero-UUID pasture-system/default identity. It is the default committing actor for system-authored operations (e.g. legacy-baseline migration).

func PastureSystemDefaultEntry

func PastureSystemDefaultEntry() provenance.FixedActorEntry

PastureSystemDefaultEntry is the fixed-actor manifest entry activation seeds for ordinal zero: pasture-system/default, kind software_agent.

func PastureSystemDefaultRegistration

func PastureSystemDefaultRegistration() provenance.FixedSoftwareAgentRegistration

PastureSystemDefaultRegistration is the complete atomic activation request for manifest-v1 ordinal zero. The manifest and software-agent names intentionally match so every public actor lookup returns the same durable identity.

func RoleIDFromSlotID

func RoleIDFromSlotID(slot provenance.AssignmentSlotID) (portable.RoleID, error)

RoleIDFromSlotID converts a Provenance AssignmentSlotID back to a portable RoleID. It round-trips exactly with SlotIDFromRoleID.

func SlotIDFromRoleID

func SlotIDFromRoleID(role portable.RoleID) (provenance.AssignmentSlotID, error)

SlotIDFromRoleID converts a portable RoleID to a Provenance AssignmentSlotID (the responsibility-slot domain; see the package NOTE on AssignmentRoleID).

func TaskIDFromRef

func TaskIDFromRef(ref portable.TaskRef) (provenance.TaskID, error)

TaskIDFromRef converts a portable TaskRef to a Provenance TaskID. The TaskRef's spelling must be a valid "namespace/uuid" wire form; a portable reference that is not a task identity (wrong domain) is rejected.

func TaskRefFromID

func TaskRefFromID(id provenance.TaskID) (portable.TaskRef, error)

TaskRefFromID converts a Provenance TaskID back to a portable TaskRef. It round-trips exactly with TaskIDFromRef.

func ValidateActorID

func ValidateActorID(id provenance.ActorID) error

ValidateActorID rejects a structurally invalid ActorID: the zero value (empty namespace) is never a usable identity, while a namespaced all-zero UUID (the pasture-system/default identity) is valid. This is the boundary check the adapter applies before handing an actor to a store call.

Types

type ActivationResult

type ActivationResult struct {
	DefaultActorID provenance.ActorID
}

ActivationResult identifies the exact default actor installed by activation. Success means the namespace claim, software-agent rows, and manifest entry all exist atomically; callers do not need a race-prone fresh-versus-retry flag.

func ActivatePastureSystem

func ActivatePastureSystem(tr provenance.Tracker) (ActivationResult, error)

ActivatePastureSystem atomically claims the pasture-system namespace, reserves fixed-UUID ordinals 0..1023, and installs only ordinal zero as the fixed pasture-system/default software agent. Exact retries are inert, claim-only persisted state is repaired, and any claim, actor, or manifest conflict aborts without partial writes. Ordinals 1..1023 remain unmaterialized.

type ApplyRequest

type ApplyRequest struct {
	// Mutation is the portable idempotency handle for this logical operation; it
	// converts to the Provenance OperationID the §9.4 replay short-circuit keys on,
	// so a stable Mutation across retries is a stable OperationID.
	Mutation portable.MutationRef
	// Actor is the already-resolved committing actor of the whole operation (§2.1):
	// the pasture-system default from activation, or a historical actor from
	// HistoricalActorID. It is validated with ValidateActorID before the store call.
	Actor provenance.ActorID
	// Authority is the JournalID of the bootstrap/assignment authority this
	// operation executes under; nil marks a genesis operation whose sole effect is
	// one bootstrap authority (§4.6, §10 rule 6).
	Authority *provenance.JournalID
	// Command is the #43-produced canonical command digest; the facade maps it
	// byte-preservingly to the Provenance CommandDigest with no re-canonicalization
	// and no caller digest flag (digest.go).
	Command ir.CanonicalCommandDigest
	// RecordedAt is the caller-supplied wall-clock stamp copied onto the operation
	// anchor for audit/display only (§12); it never establishes causality or order.
	RecordedAt int64
	// Effects is the caller-validated, #43-produced operation body folded in slice
	// order (§9.3.1). The facade neither defines nor interprets it.
	Effects []provenance.Effect
}

ApplyRequest is one logical operation expressed in the adapter's boundary vocabulary. The facade converts Mutation and Command through the adapter's own conversions (OperationIDFromRef, CommandDigestBytes) and validates Actor before touching the journal; Effects are the caller-validated, #43-produced operation body passed through opaquely.

type BaselineMigrationOutcome

type BaselineMigrationOutcome struct {
	Result          provenance.MigrationResult
	OrderedRowIDs   []provenance.TaskID
	SourceUnchanged bool
}

BaselineMigrationOutcome reports how a coordinated migration resolved. Result is the released whole-batch MigrationResult (fresh vs short-circuited anchor counts, §13); OrderedRowIDs is the deterministic (RecordedAt, LegacyRowID) presentation order the coordinator applied; SourceUnchanged is true once the post-migration source hash matched the pre-migration hash.

func RunBaselineMigration

func RunBaselineMigration(j provenance.Journal, req BaselineMigrationRequest, hashSource SourceHasher) (BaselineMigrationOutcome, error)

RunBaselineMigration drives one finite, deterministic, read-only-verified legacy-baseline migration over the pinned Provenance MigrateLegacyBaseline. It sorts the rows by (RecordedAt, LegacyRowID), hashes the source before and after, runs the whole-batch migration, and re-verifies source integrity on both the success and failure paths.

On a Provenance migration rejection (unmappable owner, schema mismatch, injected fault) the batch commits nothing and the typed error is returned verbatim for errors.Is/As; the coordinator still re-checks source integrity so a caller learns if a partial/aborted run somehow perturbed the source. On success the returned outcome carries the whole-batch MigrationResult and SourceUnchanged=true.

type BaselineMigrationRequest

type BaselineMigrationRequest struct {
	// System is the migration's committing actor (the pasture-system actor, §2.1),
	// validated with ValidateActorID before the batch runs.
	System provenance.ActorID
	// BootstrapAuthority is the genesis-established bootstrap authority JournalID the
	// per-task baseline anchors execute under (§4.6, §13).
	BootstrapAuthority provenance.JournalID
	// Owners resolves a legacy owner string to a registered ActorID. A non-empty
	// legacy owner absent from this map fails the WHOLE batch (§13 item 4).
	Owners map[string]provenance.ActorID
	// Rows are the legacy task rows to migrate, in any input order.
	Rows []provenance.LegacyTaskRow
}

BaselineMigrationRequest is the coordinator's whole-batch request. It mirrors the released provenance.MigrationInput but names the committing system actor and the established genesis bootstrap authority explicitly, and takes the legacy rows in any order (the coordinator sorts them deterministically before presenting them).

type Journal

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

Journal is the thin facade over a single Provenance Journal. Construct it with NewJournal over the Journal from an open Provenance tracker; every mutation flows through the one underlying journal, so there is no split write path.

func NewJournal

func NewJournal(api provenance.Journal) (*Journal, error)

NewJournal wraps a Provenance Journal (e.g. Tracker.Journal()) in the facade. A nil api is rejected so the failure surfaces at construction rather than as a nil-dereference on the first call.

func (*Journal) Apply

func (j *Journal) Apply(req ApplyRequest) (Outcome, error)

Apply commits one logical operation atomically through the single journal write path (§9.5). It converts the mutation reference to an OperationID, the canonical command digest to raw Provenance command-digest bytes, and validates the committing actor, then folds the caller's effects in one operation. It returns:

  • OutcomeCommitted, nil — the operation committed (fresh) or replayed idempotently (Committed.ShortCircuited is true on a §9.4 replay).
  • OutcomeConflict, err — the OperationID was reused with a differing four-field identity (§11); nothing was committed and err wraps provenance.ErrOperationConflict for errors.Is/As recovery.
  • zero Outcome, err — a boundary conversion or journal error (validation, authority scope, genesis discipline, …), returned verbatim.

func (*Journal) LookupCommitted

func (j *Journal) LookupCommitted(mutation portable.MutationRef) (Outcome, error)

LookupCommitted returns the side-effect-free committed result for a mutation reference (§9.4). It converts the reference to an OperationID and reads the journal, returning OutcomeAbsent for a never-applied operation (nil error, no side effects) or OutcomeCommitted with the reconstructed result. It never returns OutcomeConflict: a lookup compares no identity, so an absent and a committed result are the only closed variants (§3.2).

type LegacyAuditEvent

type LegacyAuditEvent struct {
	// LegacyRowID is the row's identity within its source table; it is the
	// total-order tiebreak in the deterministic listing order.
	LegacyRowID string
	// SourceTable is the source-identity qualifier the row was extracted from, kept
	// so #43 can attribute a raw row to its origin.
	SourceTable string
	// RecordedAt is the row's original recorded wall-clock time; it is the primary
	// key of the deterministic (RecordedAt, LegacyRowID) listing order.
	RecordedAt time.Time
	// RawActor is the legacy actor text exactly as stored — uninterpreted and
	// unresolved. An empty string is preserved as an empty string.
	RawActor string
	// RawContexts are the original context strings in source order, preserved
	// verbatim (never deduplicated or reordered).
	RawContexts []string
	// Payload is the opaque source payload, byte-preserved. It is copied defensively
	// on extraction so the returned event cannot alias the source's buffer.
	Payload json.RawMessage
}

LegacyAuditEvent is one raw non-task legacy audit row, preserved verbatim for #43's typed import. Every field is the source's original value with no interpretation: RawActor keeps the legacy actor string exactly (it is NOT resolved to an ActorID here — an unmapped legacy actor is a first-class value), RawContexts keeps the original context strings in source order, Payload is the opaque source bytes byte-preserved, and SourceTable + LegacyRowID together are the row's source identity.

func ListLegacyAuditEvents

func ListLegacyAuditEvents(src LegacyAuditSource) ([]LegacyAuditEvent, error)

ListLegacyAuditEvents extracts all non-task legacy audit rows from src read-only and returns them in the deterministic (RecordedAt, LegacyRowID) display order, preserving each row's raw actor text, contexts, and source identity verbatim. It is the API #43's CLI wires; it performs no import, no normalisation, and no CLI I/O.

The returned slice is a fresh, independently-owned copy: RawContexts and Payload are deep-copied so a caller mutating the result can never reach back into the source's buffers, keeping the extraction strictly read-only.

type LegacyAuditSource

type LegacyAuditSource interface {
	// ExtractLegacyAuditEvents returns every non-task legacy audit row read-only, in
	// any order. It must not mutate the source. An extraction failure is returned as
	// an error, which ListLegacyAuditEvents surfaces verbatim.
	ExtractLegacyAuditEvents() ([]LegacyAuditEvent, error)
}

LegacyAuditSource is the read-only extractor #43's CLI supplies for the concrete pre-journal audit source (the released Provenance surface does not own the legacy audit schema, so the source is provided by the caller). The coordinator calls it exactly once per listing and never mutates it.

type Outcome

type Outcome struct {
	Kind      OutcomeKind
	Committed provenance.CommittedResult
	Conflict  *provenance.OperationConflict
}

Outcome is the closed result of a facade Apply or LookupCommitted. Committed carries the underlying provenance.CommittedResult verbatim (anchor JournalID, the emitted task-event closure in JournalID order, and the slot-keyed result bindings) for the OutcomeCommitted case; Conflict carries the typed provenance.OperationConflict for the OutcomeConflict case. Both are the exact values Provenance returned — the facade re-shapes only the discriminator, never the payload.

type OutcomeKind

type OutcomeKind int

OutcomeKind is the closed variant of a facade Apply/LookupCommitted result. It is a 1:1 mirror of provenance.CommittedResultKind, re-expressed in the adapter's own vocabulary so callers switch on a total, exhaustive set.

const (
	// OutcomeAbsent: no committed operation exists for the mutation reference.
	// LookupCommitted returns this with a nil error and no side effects; Apply
	// never returns it (a fresh Apply either commits or conflicts).
	OutcomeAbsent OutcomeKind = iota
	// OutcomeCommitted: the operation is committed. For a fresh Apply it is the
	// just-folded result; for a replayed Apply or a LookupCommitted it is the
	// reconstructed already-committed result (Committed.ShortCircuited distinguishes
	// an idempotent Apply replay).
	OutcomeCommitted
	// OutcomeConflict: the mutation reference was reused with a differing four-field
	// replay identity (§11). Only Apply produces it; nothing was committed.
	OutcomeConflict
)

func (OutcomeKind) String

func (k OutcomeKind) String() string

type SourceHasher

type SourceHasher func() ([]byte, error)

SourceHasher returns a stable byte digest of the external pre-journal source the migration reads from. The coordinator calls it immediately before and after the migration and requires byte-equality, so it must be a deterministic function of the source's persisted bytes (e.g. a hash of the ordered legacy rows or a content hash of the source tables). It reads only; it must never mutate the source.

Jump to

Keyboard shortcuts

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