Skip to main content

internal/infra/pg/factreceipt.go

internal/infra/pg · 223 lines · 8 declarations · source

Declarations

const MaxRecoveryPage

const MaxRecoveryPage = 100

source

var ErrInvalidRecovery

var ErrInvalidRecovery = errors.New("recovery requires a valid cursor, source and page size")

source

var ErrInvalidReceipt

var ErrInvalidReceipt = errors.New("formation receipt no longer matches its surviving source")

source

type RecoveryPage

type RecoveryPage struct {
Examined int `json:"examined"`
Restored int `json:"restored"`
Repaired int `json:"repaired"`
Next string `json:"next,omitempty"`
}

RecoveryPage is a live UUID page. Repeating a page preserves retained records, and an interrupted transaction advances nothing. A new full pass finds concurrent additions below a previous cursor.

source

method FactStore.RecoverFacts

func (s *FactStore) RecoverFacts(ctx context.Context, schema Schema, scope, source, after, principal string, limit int) (RecoveryPage, error)

RecoverFacts restores one bounded page without a model call or a delete of available memory. It does not claim to regenerate embeddings, summaries, or interpretations under new model rules.

source

func restoreFactReceiptTx

func restoreFactReceiptTx(ctx context.Context, tx pgx.Tx, schema Schema, scope, id string) (bool, error)

Receipt state is a typed PostgreSQL row, not a model response. Source byte verification prevents recovery from a changed transcript. Existing rows win; recovery never restamps current memory.

source

const retainFactReceiptSQL

const retainFactReceiptSQL = `INSERT INTO {schema}.fact_receipt(scope,fact_id,source_observation_id,source_ordinal,state,evidence,subject_identity,object_identity,pipeline_version,supersession_source,superseded_by)
SELECT f.scope,f.fact_id,e.source_observation_id,e.source_ordinal,to_jsonb(f),to_jsonb(e),
to_jsonb(l)-'aliases'-'normalized_aliases',to_jsonb(r)-'aliases'-'normalized_aliases',d.pipeline_version,f.supersession_source,f.superseded_by
FROM {schema}.fact f JOIN {schema}.fact_evidence e ON e.scope=f.scope AND e.fact_id=f.fact_id
JOIN {schema}.projection_dependency d ON d.scope=f.scope AND d.fact_ref=f.fact_id AND d.source_observation_id=e.source_observation_id
LEFT JOIN {schema}.entity l ON l.scope=f.scope AND l.entity_id=f.subject_entity_id
LEFT JOIN {schema}.entity r ON r.scope=f.scope AND r.entity_id=f.object_entity_id
WHERE f.scope=$1 AND f.fact_id=$2::uuid ON CONFLICT(scope,fact_id) DO NOTHING`

source

func receiptOwnershipSQLFor

func receiptOwnershipSQLFor(table, owned string) string

receiptOwnershipSQLFor is the ownership predicate over any subquery of owned observation ids, so an erasure by source counts receipts exactly as an erasure by subject does, and both governance readers — the export and the erasure — ask the question in exactly one way. The table names are a fixed internal set.

source