{"id":"linked-art/partitioning","relativePath":"linked-art/partitioning.md","title":"Linked Art Graph Partitioning","markdown":"# Linked Art Graph Partitioning\n\nMeta Museum now has a reusable partition planner for the hard case where a\nvalid Linked Art graph needs to be emitted as discrete Linked Art API endpoint\ndocuments.\n\nThe implementation lives in `src/utils/linked-art-partitioner.ts` and is covered\nby `tests/utils/linked-art-partitioner.test.ts`.\n\n## Policy\n\n- First-class endpoint nodes (`HumanMadeObject`, `Person`, `Group`, `Place`,\n  `Type`, `Set`, `Activity`, `Event`, `ProvenanceActivity`, textual/visual works,\n  and related Linked Art endpoint classes) become their own documents.\n- Cross-document relationships become compact references with `id`, `type`, and\n  `_label`, rather than recursively embedding a whole graph.\n- Owned embedded structures remain embedded where Linked Art expects them, such\n  as names, dimensions, timespans, provenance `part[]` activities, and lifecycle\n  activity summaries.\n- Dereferenceable embedded activity/shared-structure nodes receive\n  `_complete: false` through the existing completeness projection policy.\n- Recursive relationships such as object `part`/`part_of`, set `member`/\n  `member_of`, concept `broader`, and provenance activity `part[]` are bounded\n  with depth and visited-node checks.\n- When the same URI appears as both a compact nested reference and a richer\n  graph node, the planner keeps the richer occurrence for the partition document.\n\n## Evidence Fixtures\n\nThe regression suite covers:\n\n- Recursive physical-object parts.\n- Reused activity nodes that are embedded as summaries and also emitted as full\n  event/activity documents.\n- Archival set hierarchy and concept `broader`/`member_of` recursion.\n- Provenance wrapper activities with embedded acquisition/payment parts and\n  referenced participants.\n- Optional official Linked Art endpoint JSON Schema validation on generated\n  partition documents.\n\n## Current Boundary\n\nThe first production adoption paths are:\n\n- `/api/events/{id}` for ActivityStreams `linkedArt.id` dereferences. Activity\n  subclasses such as `Production` are routed through the Event/Activity endpoint\n  family, and relationships such as `used_specific_object`, `carried_out_by`,\n  and `produced` are bounded as compact references when they cross into other\n  endpoint documents.\n- `/api/sets/{id}` for stored Set hierarchy records. `member` and `member_of`\n  recursion is bounded as compact Set references when the Set is available as a\n  stored record. Nested-only referenced sets still fall back to the entity-index\n  profile so relation discovery remains available.\n- `/api/concepts/{id}` for stored Concept hierarchy records. `broader` and\n  `member_of` recursion is bounded as compact concept/set references while\n  preserving the concept endpoint family shape.\n- `/api/objects/{id}` for stored physical object records. Object `part` and\n  `part_of` recursion is bounded as compact `HumanMadeObject` references, while\n  owned lifecycle summaries such as `produced_by` stay embedded and their\n  cross-document actor/place/object relationships stay compact.\n- `/api/records/{id}` for canonical record detail responses. This route runs the\n  planner only after it rewrites the stored id to the canonical MetaMuseum detail\n  URL and rebuilds `equivalent[]`, then adopts the planner output only for\n  sensitive recursive/root-activity fields such as `part`, `part_of`,\n  `member_of`, `broader`, and `produced_by`. The broader record-detail envelope\n  keeps local metadata such as `_source`, `schemaVersion`, and `_links.self` so\n  existing consumers still receive a rich detail record rather than a thin\n  endpoint partition.\n\nThis is not yet the universal serialization path for every public route.\nExisting endpoint serializers can adopt it incrementally. The next implementation\nstep is to route additional provider-specific/entity-detail serializers through\nthe same helper style only where planner output reduces duplicate case-by-case\nrecursion logic without weakening their public response contracts.\n","sections":[{"level":2,"heading":"Policy","anchor":"policy"},{"level":2,"heading":"Evidence Fixtures","anchor":"evidence-fixtures"},{"level":2,"heading":"Current Boundary","anchor":"current-boundary"}],"html":"<h1 id=\"linked-art-graph-partitioning\">Linked Art Graph Partitioning</h1>\n<p>Meta Museum now has a reusable partition planner for the hard case where a</p>\n<p>valid Linked Art graph needs to be emitted as discrete Linked Art API endpoint</p>\n<p>documents.</p>\n<p>The implementation lives in `src/utils/linked-art-partitioner.ts` and is covered</p>\n<p>by `tests/utils/linked-art-partitioner.test.ts`.</p>\n<h2 id=\"policy\">Policy</h2>\n<p>  `Type`, `Set`, `Activity`, `Event`, `ProvenanceActivity`, textual/visual works,</p>\n<p>  and related Linked Art endpoint classes) become their own documents.</p>\n<p>  `_label`, rather than recursively embedding a whole graph.</p>\n<p>  as names, dimensions, timespans, provenance `part[]` activities, and lifecycle</p>\n<p>  activity summaries.</p>\n<p>  `_complete: false` through the existing completeness projection policy.</p>\n<p>  `member_of`, concept `broader`, and provenance activity `part[]` are bounded</p>\n<p>  with depth and visited-node checks.</p>\n<p>  graph node, the planner keeps the richer occurrence for the partition document.</p>\n<ul><li>First-class endpoint nodes (`HumanMadeObject`, `Person`, `Group`, `Place`,</li><li>Cross-document relationships become compact references with `id`, `type`, and</li><li>Owned embedded structures remain embedded where Linked Art expects them, such</li><li>Dereferenceable embedded activity/shared-structure nodes receive</li><li>Recursive relationships such as object `part`/`part_of`, set `member`/</li><li>When the same URI appears as both a compact nested reference and a richer</li></ul>\n<h2 id=\"evidence-fixtures\">Evidence Fixtures</h2>\n<p>The regression suite covers:</p>\n<p>  event/activity documents.</p>\n<p>  referenced participants.</p>\n<p>  partition documents.</p>\n<ul><li>Recursive physical-object parts.</li><li>Reused activity nodes that are embedded as summaries and also emitted as full</li><li>Archival set hierarchy and concept `broader`/`member_of` recursion.</li><li>Provenance wrapper activities with embedded acquisition/payment parts and</li><li>Optional official Linked Art endpoint JSON Schema validation on generated</li></ul>\n<h2 id=\"current-boundary\">Current Boundary</h2>\n<p>The first production adoption paths are:</p>\n<p>  subclasses such as `Production` are routed through the Event/Activity endpoint</p>\n<p>  family, and relationships such as `used_specific_object`, `carried_out_by`,</p>\n<p>  and `produced` are bounded as compact references when they cross into other</p>\n<p>  endpoint documents.</p>\n<p>  recursion is bounded as compact Set references when the Set is available as a</p>\n<p>  stored record. Nested-only referenced sets still fall back to the entity-index</p>\n<p>  profile so relation discovery remains available.</p>\n<p>  `member_of` recursion is bounded as compact concept/set references while</p>\n<p>  preserving the concept endpoint family shape.</p>\n<p>  `part_of` recursion is bounded as compact `HumanMadeObject` references, while</p>\n<p>  owned lifecycle summaries such as `produced_by` stay embedded and their</p>\n<p>  cross-document actor/place/object relationships stay compact.</p>\n<p>  planner only after it rewrites the stored id to the canonical MetaMuseum detail</p>\n<p>  URL and rebuilds `equivalent[]`, then adopts the planner output only for</p>\n<p>  sensitive recursive/root-activity fields such as `part`, `part_of`,</p>\n<p>  `member_of`, `broader`, and `produced_by`. The broader record-detail envelope</p>\n<p>  keeps local metadata such as `_source`, `schemaVersion`, and `_links.self` so</p>\n<p>  existing consumers still receive a rich detail record rather than a thin</p>\n<p>  endpoint partition.</p>\n<ul><li>`/api/events/{id}` for ActivityStreams `linkedArt.id` dereferences. Activity</li><li>`/api/sets/{id}` for stored Set hierarchy records. `member` and `member_of`</li><li>`/api/concepts/{id}` for stored Concept hierarchy records. `broader` and</li><li>`/api/objects/{id}` for stored physical object records. Object `part` and</li><li>`/api/records/{id}` for canonical record detail responses. This route runs the</li></ul>\n<p>This is not yet the universal serialization path for every public route.</p>\n<p>Existing endpoint serializers can adopt it incrementally. The next implementation</p>\n<p>step is to route additional provider-specific/entity-detail serializers through</p>\n<p>the same helper style only where planner output reduces duplicate case-by-case</p>\n<p>recursion logic without weakening their public response contracts.</p>","updatedAt":"2018-10-20T01:46:40.000Z","checksum":"341aff71f753fa6ff99798603baa9af76314629e20560e7a1750b948a1d9b8b8","checksumPrefix":"341aff71f753","anchorCount":3,"lineCount":75,"rawUrl":"/api/docs/content?path=linked-art%2Fpartitioning.md","htmlUrl":"/docs?doc=linked-art%2Fpartitioning.md","apiUrl":"/api/docs/content?path=linked-art%2Fpartitioning.md"}