Skip to content
🚧 Early alpha — building the foundation. See the roadmap →

Link metadata system

Updated

Traditional markdown links only store a destination. You can link to AC-2.md but you can’t express why — is it evidence? An implementation? A review? Crosswalker’s future link system encodes metadata about relationships, not just the relationships themselves.

Edge metadata is additional information stored about a link between two notes:

  • A dotKey (e.g., framework_here.reviewer) naming the relationship type
  • A value — boolean, string, or JSON object with richer details
  • A destination — WikiLink or markdown link to the target note
# Boolean (implied true)
framework_here.applies_to:: [[AC-2]]

# String value
framework_here.reviewer:: "Alice"

# JSON metadata
framework_here.applies_to:: [[AC-2]] {"sufficient": true, "reviewer": "Alice"}

# Markdown link style
framework_here.applies_to:: [AC-2](path/to/AC-2.md) {"status": "complete"}

# Wrapped (hidden in Obsidian reading view)
[framework_here.applies_to:: [[AC-2]]]
(framework_here.applies_to:: [[AC-2]] {"sufficient": true})

The dot notation in framework_here.applies_to serves three purposes:

  1. Default value for outgoing links — sets a default that applies to all links from this note
  2. Boolean flag — when no JSON follows, the relationship is implicitly true
  3. Object default — when JSON follows without a link, sets default properties for all links of that type

When edge metadata appears in multiple places (frontmatter, inline tags, folder attributes), a priority hierarchy resolves conflicts:

PrioritySourceExample
1 (highest)Inline tag + link + JSONtype:: [[Target]] {"key": "val"}
2Inline tag + link (implied boolean)type:: [[Target]]
3Inline tag (child/leaf) + link + JSONNested folder context
4Inline tag (parent/root) + link + JSONParent folder context
5Inline tag without link + valuetype:: "default_value"
6YAML frontmattertype: value in frontmatter
7 (lowest)Folder-level defaultsInherited from parent folder

The system uses regex to extract structured data from inline link syntax:

framework_here.applies_to:: [[ID 12]] {"sufficient": true, "control": true}

Captured groups:

  • dotKey: framework_here.applies_to
  • destination: [[ID 12]] (WikiLink), [ID 12](path.md) (markdown), or plain text
  • metadata: {"sufficient": true, "control": true} (JSON) or "quoted value"

Relationships can be queried at different hierarchical levels:

At a specific framework node (e.g., AC-2.md), find all notes that link to it with their metadata.

Aggregate all inbound links for an entire folder (e.g., all Access Control family controls), merging or grouping results.

Search the entire vault for any note linking to any part of the framework, producing a compliance-wide view.

When multiple notes link to the same framework node, their metadata must be aggregated:

  • A single control might be referenced by 5 evidence notes, each with different reviewers and coverage levels
  • The aggregation uses the priority structure to merge conflicting values
  • Output can be nested (JSON/YAML), tabular, or pivoted by category

The link metadata system is designed but not yet implemented in the Crosswalker plugin. The current MVP focuses on importing structured data. The link system is planned for Phase 2 — see the roadmap.

The Python tool (frameworks_to_obsidian.py) generates basic WikiLinks between framework nodes. The plugin will eventually support the full typed-link syntax described here.

For the complete syntax reference including wrapping styles, link types, the production regex, and the two-tier priority system, see the link metadata syntax specification.

The typed-link syntax relies on Dataview inline fields. The Obsidian metadata ecosystem is evolving:

ComponentProperties (native)DataviewBases (native)Datacore
Frontmatter queriesRead onlyFullFull + formulasFull
Inline field queriesNoYesNoTBD
Edge metadata extractionNoVia DataviewJSNoTBD
Tabular displayNoTABLE queriesNative viewsTBD
Bases limitation
Obsidian Bases is tabular-only — it can query frontmatter properties but cannot process inline fields, traverse typed links, or extract edge metadata. DataviewJS (or future Datacore) is required for relationship-level queries.

Design principle: Store all non-link metadata as YAML frontmatter (queryable everywhere). Reserve inline fields for typed-link edge metadata only (requires Dataview/Datacore).