@x12i/memorix-format 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +90 -0
  2. package/dist/associated.d.ts +38 -0
  3. package/dist/associated.d.ts.map +1 -0
  4. package/dist/associated.js +59 -0
  5. package/dist/associated.js.map +1 -0
  6. package/dist/cli.d.ts +3 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +199 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/concept.d.ts +16 -0
  11. package/dist/concept.d.ts.map +1 -0
  12. package/dist/concept.js +75 -0
  13. package/dist/concept.js.map +1 -0
  14. package/dist/constants.d.ts +21 -0
  15. package/dist/constants.d.ts.map +1 -0
  16. package/dist/constants.js +49 -0
  17. package/dist/constants.js.map +1 -0
  18. package/dist/index.d.ts +9 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +7 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/inspect.d.ts +4 -0
  23. package/dist/inspect.d.ts.map +1 -0
  24. package/dist/inspect.js +51 -0
  25. package/dist/inspect.js.map +1 -0
  26. package/dist/types.d.ts +81 -0
  27. package/dist/types.d.ts.map +1 -0
  28. package/dist/types.js +2 -0
  29. package/dist/types.js.map +1 -0
  30. package/dist/utils.d.ts +6 -0
  31. package/dist/utils.d.ts.map +1 -0
  32. package/dist/utils.js +23 -0
  33. package/dist/utils.js.map +1 -0
  34. package/dist/validate.d.ts +14 -0
  35. package/dist/validate.d.ts.map +1 -0
  36. package/dist/validate.js +211 -0
  37. package/dist/validate.js.map +1 -0
  38. package/docs/association-format.md +466 -0
  39. package/docs/memorix-format-additions.md +956 -0
  40. package/docs/memorix-format-for-dummies-association-corrections.md +113 -0
  41. package/docs/memorix-format.md +282 -0
  42. package/docs/memorix-workflow-format.md +114 -0
  43. package/examples/invalid-record.json +11 -0
  44. package/examples/valid-snapshot.json +38 -0
  45. package/package.json +67 -0
@@ -0,0 +1,51 @@
1
+ import { CANONICAL_ROOT_KEYS, LEGACY_ROOT_KEYS } from "./constants.js";
2
+ import { listAssociatedProperties } from "./associated.js";
3
+ import { readConceptIdentifier, readConceptTitle, readRecordId } from "./concept.js";
4
+ import { isPlainObject } from "./utils.js";
5
+ /** Summarize which format buckets and associated properties a record uses. */
6
+ export function inspectMemorixRecord(input) {
7
+ if (!isPlainObject(input)) {
8
+ return {
9
+ buckets: {
10
+ data: false,
11
+ analytics: false,
12
+ enrichment: false,
13
+ insights: false,
14
+ system: false,
15
+ },
16
+ associatedProperties: [],
17
+ legacyRoots: [],
18
+ unknownRoots: [],
19
+ };
20
+ }
21
+ const record = input;
22
+ const conceptId = readConceptIdentifier(record);
23
+ const associatedProperties = listAssociatedProperties(record);
24
+ const legacyRoots = [];
25
+ const unknownRoots = [];
26
+ for (const key of Object.keys(record)) {
27
+ if (CANONICAL_ROOT_KEYS.has(key) || associatedProperties.includes(key))
28
+ continue;
29
+ if (LEGACY_ROOT_KEYS.has(key)) {
30
+ legacyRoots.push(key);
31
+ continue;
32
+ }
33
+ unknownRoots.push(key);
34
+ }
35
+ return {
36
+ recordId: readRecordId(record) || undefined,
37
+ conceptTitle: readConceptTitle(record),
38
+ conceptKind: conceptId?.kind,
39
+ buckets: {
40
+ data: isPlainObject(record.data),
41
+ analytics: isPlainObject(record.analytics),
42
+ enrichment: isPlainObject(record.enrichment),
43
+ insights: isPlainObject(record.insights),
44
+ system: isPlainObject(record._system),
45
+ },
46
+ associatedProperties,
47
+ legacyRoots: legacyRoots.sort(),
48
+ unknownRoots: unknownRoots.sort(),
49
+ };
50
+ }
51
+ //# sourceMappingURL=inspect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inspect.js","sourceRoot":"","sources":["../src/inspect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAErF,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C,8EAA8E;AAC9E,MAAM,UAAU,oBAAoB,CAAC,KAAc;IACjD,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO;YACL,OAAO,EAAE;gBACP,IAAI,EAAE,KAAK;gBACX,SAAS,EAAE,KAAK;gBAChB,UAAU,EAAE,KAAK;gBACjB,QAAQ,EAAE,KAAK;gBACf,MAAM,EAAE,KAAK;aACd;YACD,oBAAoB,EAAE,EAAE;YACxB,WAAW,EAAE,EAAE;YACf,YAAY,EAAE,EAAE;SACjB,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAe,KAAK,CAAC;IACjC,MAAM,SAAS,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,oBAAoB,GAAG,wBAAwB,CAAC,MAAM,CAAC,CAAC;IAC9D,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,MAAM,YAAY,GAAa,EAAE,CAAC;IAElC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACtC,IAAI,mBAAmB,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,oBAAoB,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,SAAS;QACjF,IAAI,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9B,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACtB,SAAS;QACX,CAAC;QACD,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,YAAY,CAAC,MAAM,CAAC,IAAI,SAAS;QAC3C,YAAY,EAAE,gBAAgB,CAAC,MAAM,CAAC;QACtC,WAAW,EAAE,SAAS,EAAE,IAAI;QAC5B,OAAO,EAAE;YACP,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC;YAChC,SAAS,EAAE,aAAa,CAAC,MAAM,CAAC,SAAS,CAAC;YAC1C,UAAU,EAAE,aAAa,CAAC,MAAM,CAAC,UAAU,CAAC;YAC5C,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,QAAQ,CAAC;YACxC,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC;SACtC;QACD,oBAAoB;QACpB,WAAW,EAAE,WAAW,CAAC,IAAI,EAAE;QAC/B,YAAY,EAAE,YAAY,CAAC,IAAI,EAAE;KAClC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,81 @@
1
+ /** Plain JSON object (non-array). */
2
+ export type JsonObject = Record<string, unknown>;
3
+ /** Discriminated concept identifier with deterministic join key. */
4
+ export type MemorixConceptIdentifier = {
5
+ kind: string;
6
+ /** Deterministic join key: kind first, then values, colon-joined. */
7
+ identifierKey: string;
8
+ [key: string]: string;
9
+ };
10
+ export type MemorixConcept = {
11
+ identifier: MemorixConceptIdentifier;
12
+ title: string;
13
+ };
14
+ export type MemorixLifecycleEvent = {
15
+ process: string;
16
+ processedAt: string;
17
+ };
18
+ export type MemorixSystemBlock = {
19
+ lifecycle?: MemorixLifecycleEvent[];
20
+ _graphRuns?: Record<string, unknown>;
21
+ _jobTypeRuns?: Record<string, unknown>;
22
+ provenance?: JsonObject;
23
+ memorix?: JsonObject;
24
+ processing?: JsonObject;
25
+ scoping?: JsonObject;
26
+ [key: string]: unknown;
27
+ };
28
+ /**
29
+ * Canonical clean Memorix record envelope.
30
+ * See `docs/memorix-format.md`.
31
+ */
32
+ export type MemorixRecord = {
33
+ _id?: unknown;
34
+ recordId: string;
35
+ concept: MemorixConcept;
36
+ data: JsonObject;
37
+ analytics?: JsonObject;
38
+ enrichment?: JsonObject;
39
+ insights?: JsonObject;
40
+ /** Legacy short name; prefer v2 `associated<ObjectType><ContentType>`. */
41
+ associatedData?: JsonObject[];
42
+ _system?: MemorixSystemBlock;
43
+ };
44
+ /** Optional content-type hint for snapshot-only bucket rules. */
45
+ export type MemorixContentTypeHint = "snapshots" | "discovery" | "analysis" | "decision" | "workflow" | "chunks" | "facts" | "events" | "history" | "profiles" | "legacy" | "core" | "inferences" | "scoped" | (string & {});
46
+ export type ValidationSeverity = "error" | "warning";
47
+ export type ValidationIssue = {
48
+ path: string;
49
+ code: string;
50
+ message: string;
51
+ severity: ValidationSeverity;
52
+ };
53
+ export type ValidateRecordOptions = {
54
+ /** When set and not `snapshots`, snapshot-only buckets are rejected. */
55
+ contentType?: MemorixContentTypeHint;
56
+ /** Allow root `identity` / `lifecycle` / `sourceFacts` (legacy 2.0). Default false. */
57
+ allowLegacyEnvelope?: boolean;
58
+ /** Treat warnings as failures in `ok`. Default false. */
59
+ strict?: boolean;
60
+ };
61
+ export type ValidateRecordResult = {
62
+ ok: boolean;
63
+ issues: ValidationIssue[];
64
+ recordId?: string;
65
+ };
66
+ export type RecordInspection = {
67
+ recordId?: string;
68
+ conceptTitle?: string;
69
+ conceptKind?: string;
70
+ buckets: {
71
+ data: boolean;
72
+ analytics: boolean;
73
+ enrichment: boolean;
74
+ insights: boolean;
75
+ system: boolean;
76
+ };
77
+ associatedProperties: string[];
78
+ legacyRoots: string[];
79
+ unknownRoots: string[];
80
+ };
81
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEjD,oEAAoE;AACpE,MAAM,MAAM,wBAAwB,GAAG;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,aAAa,EAAE,MAAM,CAAC;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,EAAE,wBAAwB,CAAC;IACrC,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,CAAC,EAAE,qBAAqB,EAAE,CAAC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,cAAc,CAAC;IACxB,IAAI,EAAE,UAAU,CAAC;IACjB,SAAS,CAAC,EAAE,UAAU,CAAC;IACvB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,QAAQ,CAAC,EAAE,UAAU,CAAC;IACtB,0EAA0E;IAC1E,cAAc,CAAC,EAAE,UAAU,EAAE,CAAC;IAC9B,OAAO,CAAC,EAAE,kBAAkB,CAAC;CAC9B,CAAC;AAEF,iEAAiE;AACjE,MAAM,MAAM,sBAAsB,GAC9B,WAAW,GACX,WAAW,GACX,UAAU,GACV,UAAU,GACV,UAAU,GACV,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,SAAS,GACT,UAAU,GACV,QAAQ,GACR,MAAM,GACN,YAAY,GACZ,QAAQ,GACR,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAElB,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,SAAS,CAAC;AAErD,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,kBAAkB,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,wEAAwE;IACxE,WAAW,CAAC,EAAE,sBAAsB,CAAC;IACrC,uFAAuF;IACvF,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,yDAAyD;IACzD,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE;QACP,IAAI,EAAE,OAAO,CAAC;QACd,SAAS,EAAE,OAAO,CAAC;QACnB,UAAU,EAAE,OAAO,CAAC;QACpB,QAAQ,EAAE,OAAO,CAAC;QAClB,MAAM,EAAE,OAAO,CAAC;KACjB,CAAC;IACF,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ import type { JsonObject } from "./types.js";
2
+ export declare function isPlainObject(v: unknown): v is JsonObject;
3
+ export declare function stringifyId(value: unknown): string | null;
4
+ /** PascalCase from kebab/snake (e.g. vulnerabilities-groups → VulnerabilitiesGroups). */
5
+ export declare function pascalCaseObjectType(value: string): string;
6
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,UAAU,CAEzD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAQzD;AAED,yFAAyF;AACzF,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAM1D"}
package/dist/utils.js ADDED
@@ -0,0 +1,23 @@
1
+ export function isPlainObject(v) {
2
+ return v !== null && typeof v === "object" && !Array.isArray(v);
3
+ }
4
+ export function stringifyId(value) {
5
+ if (value == null)
6
+ return null;
7
+ if (typeof value === "string") {
8
+ const t = value.trim();
9
+ return t || null;
10
+ }
11
+ if (typeof value === "number" || typeof value === "boolean")
12
+ return String(value);
13
+ return null;
14
+ }
15
+ /** PascalCase from kebab/snake (e.g. vulnerabilities-groups → VulnerabilitiesGroups). */
16
+ export function pascalCaseObjectType(value) {
17
+ return value
18
+ .split(/[-_]/)
19
+ .filter(Boolean)
20
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
21
+ .join("");
22
+ }
23
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,aAAa,CAAC,CAAU;IACtC,OAAO,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QACvB,OAAO,CAAC,IAAI,IAAI,CAAC;IACnB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IAClF,OAAO,IAAI,CAAC;AACd,CAAC;AAED,yFAAyF;AACzF,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,OAAO,KAAK;SACT,KAAK,CAAC,MAAM,CAAC;SACb,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAC3D,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { ValidateRecordOptions, ValidateRecordResult } from "./types.js";
2
+ /**
3
+ * Validate a Memorix record against the clean envelope contract.
4
+ * Does not require Mongo or Catalox — pure shape validation.
5
+ */
6
+ export declare function validateMemorixRecord(input: unknown, options?: ValidateRecordOptions): ValidateRecordResult;
7
+ /** Validate many records; returns per-record results plus aggregate ok. */
8
+ export declare function validateMemorixRecords(records: unknown[], options?: ValidateRecordOptions): {
9
+ ok: boolean;
10
+ results: ValidateRecordResult[];
11
+ };
12
+ /** Parse JSON text that is either one object or an array / NDJSON stream. */
13
+ export declare function parseRecordsJson(text: string): unknown[];
14
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAEV,qBAAqB,EACrB,oBAAoB,EAErB,MAAM,YAAY,CAAC;AAgOpB;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,OAAO,EACd,OAAO,GAAE,qBAA0B,GAClC,oBAAoB,CAyFtB;AAED,2EAA2E;AAC3E,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,OAAO,EAAE,EAClB,OAAO,GAAE,qBAA0B,GAClC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,oBAAoB,EAAE,CAAA;CAAE,CAGlD;AAED,6EAA6E;AAC7E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,CA2BxD"}
@@ -0,0 +1,211 @@
1
+ import { ANALYTICS_FIELD, CANONICAL_ROOT_KEYS, ENRICHMENT_FIELD, INSIGHTS_FIELD, LEGACY_ROOT_KEYS, SNAPSHOT_ONLY_BUCKETS, } from "./constants.js";
2
+ import { isAssociatedPropertyName, isLegacyAssociatedPropertyName } from "./associated.js";
3
+ import { buildIdentityString, readRecordId } from "./concept.js";
4
+ import { isPlainObject, stringifyId } from "./utils.js";
5
+ function issue(path, code, message, severity = "error") {
6
+ return { path, code, message, severity };
7
+ }
8
+ function validateConcept(concept, issues) {
9
+ if (!isPlainObject(concept)) {
10
+ issues.push(issue("concept", "concept.required", "concept must be a plain object"));
11
+ return;
12
+ }
13
+ const title = stringifyId(concept.title);
14
+ if (!title) {
15
+ issues.push(issue("concept.title", "concept.title.required", "concept.title must be a non-empty string"));
16
+ }
17
+ if (concept.name !== undefined) {
18
+ issues.push(issue("concept.name", "concept.name.legacy", 'concept.name is removed in the clean format; use concept.identifier + concept.title', "warning"));
19
+ }
20
+ const identifier = concept.identifier;
21
+ if (!isPlainObject(identifier)) {
22
+ issues.push(issue("concept.identifier", "concept.identifier.required", "concept.identifier must be a plain object"));
23
+ return;
24
+ }
25
+ const kind = stringifyId(identifier.kind);
26
+ if (!kind) {
27
+ issues.push(issue("concept.identifier.kind", "concept.identifier.kind.required", "concept.identifier.kind must be a non-empty string"));
28
+ return;
29
+ }
30
+ if (identifier[kind] == null || String(identifier[kind]).trim() === "") {
31
+ issues.push(issue(`concept.identifier.${kind}`, "concept.identifier.value.required", `concept.identifier.${kind} must be present for kind "${kind}"`));
32
+ }
33
+ const identifierKey = stringifyId(identifier.identifierKey);
34
+ if (!identifierKey) {
35
+ issues.push(issue("concept.identifier.identifierKey", "concept.identifier.identifierKey.required", "concept.identifier.identifierKey is required"));
36
+ }
37
+ else {
38
+ const expected = buildIdentityString(identifier);
39
+ if (expected && identifierKey !== expected) {
40
+ issues.push(issue("concept.identifier.identifierKey", "concept.identifier.identifierKey.mismatch", `identifierKey should be "${expected}", got "${identifierKey}"`, "warning"));
41
+ }
42
+ }
43
+ for (const [key, value] of Object.entries(identifier)) {
44
+ if (typeof value !== "string") {
45
+ issues.push(issue(`concept.identifier.${key}`, "concept.identifier.value.type", `concept.identifier.${key} must be a string`));
46
+ }
47
+ }
48
+ }
49
+ function validateAssociatedProperty(name, value, issues) {
50
+ if (value === undefined)
51
+ return;
52
+ if (!Array.isArray(value)) {
53
+ issues.push(issue(name, "associated.array", `${name} must be an array of objects (omit when empty)`));
54
+ return;
55
+ }
56
+ if (value.length === 0) {
57
+ issues.push(issue(name, "associated.empty", `${name} should be omitted when empty`, "warning"));
58
+ }
59
+ for (let i = 0; i < value.length; i++) {
60
+ const item = value[i];
61
+ if (!isPlainObject(item)) {
62
+ issues.push(issue(`${name}[${i}]`, "associated.item.object", `${name}[${i}] must be a plain object`));
63
+ }
64
+ }
65
+ if (isLegacyAssociatedPropertyName(name)) {
66
+ issues.push(issue(name, "associated.legacy_name", `${name} is a legacy associated name; prefer associated<ObjectType><ContentType>`, "warning"));
67
+ }
68
+ }
69
+ function validateObjectBucket(name, value, issues) {
70
+ if (value === undefined)
71
+ return;
72
+ if (!isPlainObject(value)) {
73
+ issues.push(issue(name, `${name}.object`, `${name} must be a plain object`));
74
+ return;
75
+ }
76
+ if (Object.keys(value).length === 0) {
77
+ issues.push(issue(name, `${name}.empty`, `${name} should be omitted when empty`, "warning"));
78
+ }
79
+ }
80
+ function validateSystem(system, issues) {
81
+ if (system === undefined)
82
+ return;
83
+ if (!isPlainObject(system)) {
84
+ issues.push(issue("_system", "system.object", "_system must be a plain object"));
85
+ return;
86
+ }
87
+ const lifecycle = system.lifecycle;
88
+ if (lifecycle !== undefined) {
89
+ if (!Array.isArray(lifecycle)) {
90
+ issues.push(issue("_system.lifecycle", "system.lifecycle.array", "_system.lifecycle must be an array"));
91
+ }
92
+ else {
93
+ if (lifecycle.length === 0) {
94
+ issues.push(issue("_system.lifecycle", "system.lifecycle.empty", "_system.lifecycle should be omitted when empty", "warning"));
95
+ }
96
+ for (let i = 0; i < lifecycle.length; i++) {
97
+ const entry = lifecycle[i];
98
+ if (!isPlainObject(entry)) {
99
+ issues.push(issue(`_system.lifecycle[${i}]`, "system.lifecycle.entry", `_system.lifecycle[${i}] must be an object`));
100
+ continue;
101
+ }
102
+ if (!stringifyId(entry.process)) {
103
+ issues.push(issue(`_system.lifecycle[${i}].process`, "system.lifecycle.process", "lifecycle entry requires process"));
104
+ }
105
+ if (!stringifyId(entry.processedAt)) {
106
+ issues.push(issue(`_system.lifecycle[${i}].processedAt`, "system.lifecycle.processedAt", "lifecycle entry requires processedAt"));
107
+ }
108
+ }
109
+ }
110
+ }
111
+ for (const mapKey of ["_graphRuns", "_jobTypeRuns"]) {
112
+ const map = system[mapKey];
113
+ if (map !== undefined && !isPlainObject(map)) {
114
+ issues.push(issue(`_system.${mapKey}`, `system.${mapKey}.object`, `_system.${mapKey} must be a plain object`));
115
+ }
116
+ }
117
+ }
118
+ /**
119
+ * Validate a Memorix record against the clean envelope contract.
120
+ * Does not require Mongo or Catalox — pure shape validation.
121
+ */
122
+ export function validateMemorixRecord(input, options = {}) {
123
+ const issues = [];
124
+ if (!isPlainObject(input)) {
125
+ return {
126
+ ok: false,
127
+ issues: [issue("$", "record.object", "record must be a plain JSON object")],
128
+ };
129
+ }
130
+ const record = input;
131
+ const recordId = readRecordId(record) || undefined;
132
+ const rootRecordId = stringifyId(record.recordId);
133
+ if (!rootRecordId) {
134
+ issues.push(issue("recordId", "recordId.required", "recordId must be a non-empty string"));
135
+ }
136
+ if (!isPlainObject(record.data)) {
137
+ issues.push(issue("data", "data.required", "data must be a plain object"));
138
+ }
139
+ validateConcept(record.concept, issues);
140
+ validateObjectBucket(ANALYTICS_FIELD, record.analytics, issues);
141
+ validateObjectBucket(ENRICHMENT_FIELD, record.enrichment, issues);
142
+ validateObjectBucket(INSIGHTS_FIELD, record.insights, issues);
143
+ validateSystem(record._system, issues);
144
+ const contentType = options.contentType?.trim();
145
+ const isSnapshot = !contentType || contentType === "snapshots";
146
+ if (!isSnapshot) {
147
+ for (const bucket of SNAPSHOT_ONLY_BUCKETS) {
148
+ if (record[bucket] !== undefined) {
149
+ issues.push(issue(bucket, "snapshot_only.bucket", `${bucket} is snapshot-only by default (contentType=${contentType})`));
150
+ }
151
+ }
152
+ }
153
+ for (const key of Object.keys(record)) {
154
+ if (isAssociatedPropertyName(key)) {
155
+ if (!isSnapshot) {
156
+ issues.push(issue(key, "snapshot_only.associated", `${key} is snapshot-only by default (contentType=${contentType})`));
157
+ }
158
+ validateAssociatedProperty(key, record[key], issues);
159
+ continue;
160
+ }
161
+ if (CANONICAL_ROOT_KEYS.has(key))
162
+ continue;
163
+ if (LEGACY_ROOT_KEYS.has(key)) {
164
+ if (options.allowLegacyEnvelope) {
165
+ issues.push(issue(key, "legacy.root", `${key} is a legacy 2.0 root field`, "warning"));
166
+ }
167
+ else {
168
+ issues.push(issue(key, "legacy.root.forbidden", `${key} is not part of the clean envelope (set allowLegacyEnvelope to warn instead)`));
169
+ }
170
+ continue;
171
+ }
172
+ issues.push(issue(key, "root.unknown", `unexpected root key "${key}"`, "warning"));
173
+ }
174
+ const hasError = issues.some((i) => i.severity === "error");
175
+ const hasWarning = issues.some((i) => i.severity === "warning");
176
+ const ok = options.strict ? !hasError && !hasWarning : !hasError;
177
+ return { ok, issues, recordId };
178
+ }
179
+ /** Validate many records; returns per-record results plus aggregate ok. */
180
+ export function validateMemorixRecords(records, options = {}) {
181
+ const results = records.map((r) => validateMemorixRecord(r, options));
182
+ return { ok: results.every((r) => r.ok), results };
183
+ }
184
+ /** Parse JSON text that is either one object or an array / NDJSON stream. */
185
+ export function parseRecordsJson(text) {
186
+ const trimmed = text.trim();
187
+ if (!trimmed)
188
+ return [];
189
+ if (trimmed.startsWith("[")) {
190
+ const parsed = JSON.parse(trimmed);
191
+ if (!Array.isArray(parsed)) {
192
+ throw new Error("Expected a JSON array of records");
193
+ }
194
+ return parsed;
195
+ }
196
+ if (trimmed.startsWith("{")) {
197
+ // Prefer single object; if multiple JSON objects on separate lines, treat as NDJSON.
198
+ const lines = trimmed.split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
199
+ if (lines.length > 1 && lines.every((l) => l.startsWith("{"))) {
200
+ return lines.map((line) => JSON.parse(line));
201
+ }
202
+ return [JSON.parse(trimmed)];
203
+ }
204
+ // NDJSON without leading [
205
+ return trimmed
206
+ .split(/\r?\n/)
207
+ .map((l) => l.trim())
208
+ .filter(Boolean)
209
+ .map((line) => JSON.parse(line));
210
+ }
211
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"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"}