@x12i/memorix-associator
v1.32.0
Published
Memorix cross-record association planning, apply, verification, and associated-property metadata
Maintainers
Readme
@x12i/memorix-associator
Memorix cross-record association materialization — plan, apply, verify, and associated-property metadata.
In the full enrichment stack, the associator runs after pipeline association roll-down and before narrative-sync. See memorix-pipeline for orchestration (run-enrichment-pipeline.mjs) and how roll-down differs from cross-record joins.
Responsibilities
- Build reviewable association plans from declarative rules.
- Apply idempotent smart merges onto
associated*snapshot fields. - Write technical failure records to
<objectType>-failedcollections. - Discover and merge associated snapshot property metadata (
managed,discovered,both).
Resolver logic lives in @x12i/memorix-resolvers. This package consumes resolver output in request normalization / resolvers blocks but does not hard-code resolver types.
Associated property metadata
Discovery (FR A)
For contentType === "snapshots", any root-level field whose name starts with associated is a valid associated property — including custom names like associatedRiskScores.
Managed metadata (FR B)
Managed descriptor entries describe associated properties intentionally (linked object type, content type, value shape, refreshRuleKey).
Merge contract
mergeAssociatedPropertyDescriptors() returns one list with source: "managed" | "discovered" | "both". Managed metadata is authoritative; discovery fills gaps.
Consumer guidance
Consumers should prefer Memorix associated-property metadata when available. Until metadata is available, or when reading older/custom records, fall back to the prefix rule: root-level snapshot fields whose names start with "associated".
The well-known names associatedData, associatedInferred, and associatedAnalysis are conventions only.See ASSOCIATED_PROPERTY_CONSUMER_GUIDANCE export.
Presets and registry
Managed joins are defined in two places that must stay in sync:
| Source | Location |
|--------|----------|
| Registry (operational truth) | .operational/metadata/associated-properties-registry.json |
| Committed presets | presets/*.json + presets/manifest.json |
Regenerate and verify after registry edits:
node memorix-associator/scripts/generate-presets-from-registry.mjs
node memorix-associator/scripts/verify-presets-parity.mjs
# Single preset
node memorix-associator/scripts/generate-presets-from-registry.mjs \
--refresh-rule-key assets.subnets.snapshots.by-cidrThe enrichment orchestrator (memorix-pipeline/scripts/run-enrichment-pipeline.mjs) loads presets from presets/manifest.json per sourceObjectType and runs plan → apply for each.
API
import {
planAssociations,
applyAssociations,
verifyAssociations,
createMongoRecordStore,
buildAssociationRequestFromRegistryEntry,
findRegistryEntry,
} from "@x12i/memorix-associator";
const plan = await planAssociations(request, { store });
await applyAssociations(
{
...request,
mode: "apply",
safety: { ...request.safety, expectedPlanFingerprint: plan.planFingerprint },
},
{ store },
);
await verifyAssociations(request, { store });Running associations
Canonical guide: memorix-pipeline/docs/running-associations.md
Format spec: memorix-pipeline/docs/association-format.md
Local reference: docs/running-associations.md
Quick start
export MONGO_URI="mongodb://…"
npm run build
# From registry key (preferred for managed associations)
memorix-associator plan \
--refresh-rule-key assets.subnets.snapshots.by-cidr \
--output temp/plan.json
# From committed preset file
memorix-associator plan \
--request presets/assets.subnets.snapshots.by-cidr.json \
--output temp/plan.json
# Apply — fingerprint must match reviewed plan
memorix-associator apply \
--request presets/assets.subnets.snapshots.by-cidr.json \
--reviewed-report temp/plan.json
# Verify shapes; re-plan to confirm convergence (zero pending updates)
memorix-associator verify --request presets/assets.subnets.snapshots.by-cidr.json
memorix-associator plan --request presets/assets.subnets.snapshots.by-cidr.json- Metadata-managed:
rules[].ruleKeymust matchrefreshRuleKeyon the entity descriptor'sassociatedProperties. - Re-runs are safe: apply is append-unique and idempotent; a second plan after apply should show
associatedItemsWouldAppend: 0.
CLI reference
memorix-associator plan --request <file.json> [--output <report.json>]
memorix-associator plan --refresh-rule-key <key> [--registry <path>] [--output <report.json>]
memorix-associator apply --request <file.json> --reviewed-report <report.json> [--output <report.json>]
memorix-associator verify --request <file.json>
memorix-associator --helpDefault registry path: .operational/metadata/associated-properties-registry.json
Explorer HTTP API
When running @x12i/memorix-explorer-api:
| Method | Route | Purpose |
|--------|-------|---------|
| POST | /api/explorer/associations/plan | Dry-run plan |
| POST | /api/explorer/associations/apply | Apply with reviewed fingerprint |
| POST | /api/explorer/associations/verify | Shape verification |
| GET | /api/explorer/associations/presets | List presets from parts catalog |
| GET | /api/explorer/associations/presets/:refreshRuleKey/request | Request template |
| GET | /api/explorer/operational/associated-properties-registry | Live registry |
Read-only preset/request routes are also surfaced under /api/explorer/pipeline/parts-catalog.
