Skip to main content

File Metadata ($meta)

Status: Out of v4.0.0; the name $meta is reserved and ignored by readers (decision 0014).

The linked-metadata draft develops $meta as a future document-level carrier for scoped facts about any addressed node. The example fields below illustrate one use of $meta; they do not limit that future graph design. No linked-data meaning is assigned to 4.0.0 files by this draft.

The $meta key provides a standard location for file-level metadata in VFS JSON files without polluting the main schema.

Design Principles​

  • File-Level Only: $meta appears at the top level of VFS files, not on individual nodes
  • Open JSON: Values are plain JSON objects, no special processing required
  • Optional: Files without $meta are valid; tools must handle its absence
  • Extensible: Namespaced extensions allow tool-specific data
  • Non-Semantic: Metadata does not affect IR semantics or type checking

Relationship to Other Features​

FeaturePurposeScope
$metaOperational metadata (provenance, tooling)File-level
DecorationsSemantic annotations (docs, deprecated)IR nodes
formatVersionSchema version for parsingFile-level
AttributesType-level metadata on IR nodesNode-level

Structure​

{
"formatVersion": "4.0.0",
"name": "user",
"$meta": {
"source": "src/Domain/User.elm",
"sourceRange": { "start": [10, 1], "end": [25, 1] },
"compiler": "morphir-elm 3.0.0",
"generated": "2026-01-16T12:00:00Z",
"checksum": "sha256:a1b2c3d4...",
"extensions": {
"my-tool": { ... }
}
},
"def": { ... }
}

Standard Fields​

All standard fields are optional.

Provenance Fields​

FieldTypeDescription
sourceStringPath to the source file that generated this IR
sourceRangeSourceRangeLocation within the source file
compilerStringTool and version that generated this file
generatedStringISO 8601 timestamp of generation
checksumStringContent hash with algorithm prefix (e.g., sha256:...)

Source Range​

{
"sourceRange": {
"start": [10, 1],
"end": [25, 12]
}
}
  • start: [line, column] (1-indexed)
  • end: [line, column] (1-indexed, inclusive)

Tooling Fields​

FieldTypeDescription
editedByStringLast tool/user to modify this file
editedAtStringISO 8601 timestamp of last modification
lockedBooleanHint that file should not be auto-modified
generatedBooleanTrue if file is generated (not hand-edited)

Extensions​

The extensions field provides namespaced storage for tool-specific metadata:

{
"$meta": {
"extensions": {
"morphir-vscode": {
"foldingRanges": [[5, 10], [15, 20]],
"diagnosticLevel": "warning"
},
"my-company/custom-tool": {
"internalId": "proj-123-user",
"reviewStatus": "approved"
}
}
}
}

Namespace conventions:

  • Simple names for well-known tools: "morphir-vscode", "morphir-cli"
  • Scoped names for organization tools: "my-company/tool-name"
  • Avoid conflicts by using unique prefixes

Gleam Type Definitions​

// === meta.gleam ===

/// Source location range
pub type SourceRange {
SourceRange(
start: #(Int, Int), // (line, column) 1-indexed
end: #(Int, Int), // (line, column) 1-indexed
)
}

/// File-level metadata
pub type FileMeta {
FileMeta(
// Provenance
source: Option(String),
source_range: Option(SourceRange),
compiler: Option(String),
generated: Option(String), // ISO 8601
checksum: Option(String),

// Tooling
edited_by: Option(String),
edited_at: Option(String), // ISO 8601
locked: Option(Bool),
is_generated: Option(Bool),

// Extensions (open-ended)
extensions: Dict(String, Dynamic),
)
}

/// Parse $meta from a JSON object
pub fn parse_meta(json: Dynamic) -> Result(Option(FileMeta), DecodeError) {
case dynamic.field("$meta", dynamic.dynamic)(json) {
Ok(meta_json) -> {
use meta <- result.try(decode_file_meta(meta_json))
Ok(Some(meta))
}
Error(_) -> Ok(None) // $meta is optional
}
}

JSON Examples​

Type Definition File​

File: .morphir-dist/pkg/my-org/domain/types/user.type.json

{
"formatVersion": "4.0.0",
"name": "user",
"$meta": {
"source": "src/Domain/User.elm",
"sourceRange": { "start": [15, 1], "end": [22, 1] },
"compiler": "morphir-elm 3.2.0",
"generated": "2026-01-16T14:30:00Z",
"checksum": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
"def": {
"TypeAliasDefinition": {
"body": {
"Record": {
"fields": {
"email": "morphir/SDK:string#string",
"name": "morphir/SDK:string#string"
}
}
}
}
}
}

Value Definition File​

File: .morphir-dist/pkg/my-org/domain/values/create-user.value.json

{
"formatVersion": "4.0.0",
"name": "create-user",
"$meta": {
"source": "src/Domain/User.elm",
"sourceRange": { "start": [30, 1], "end": [45, 1] },
"compiler": "morphir-elm 3.2.0",
"generated": "2026-01-16T14:30:00Z",
"extensions": {
"morphir-analyze": {
"complexity": 5,
"purity": "pure",
"callGraph": ["validate-email", "generate-id"]
}
}
},
"def": {
"access": "Public",
"value": { ... }
}
}

Module Manifest​

File: .morphir-dist/pkg/my-org/domain/module.json

{
"formatVersion": "4.0.0",
"path": "my-org/domain",
"$meta": {
"source": "src/Domain.elm",
"compiler": "morphir-elm 3.2.0",
"generated": "2026-01-16T14:30:00Z",
"extensions": {
"morphir-docs": {
"readme": "docs/domain.md",
"examples": ["examples/domain-basic.elm"]
}
}
},
"types": ["user", "order", "product"],
"values": ["create-user", "process-order"]
}

Format File​

File: .morphir-dist/manifest.json

{
"formatVersion": "4.0.0",
"distribution": "Library",
"package": "my-org/my-project",
"version": "1.2.0",
"$meta": {
"compiler": "morphir-elm 3.2.0",
"generated": "2026-01-16T14:30:00Z",
"source": "morphir.json",
"extensions": {
"morphir-ci": {
"buildId": "build-12345",
"pipeline": "main",
"commit": "abc123def456"
}
}
}
}

Hand-Edited File​

{
"formatVersion": "4.0.0",
"name": "config",
"$meta": {
"generated": false,
"editedBy": "alice@example.com",
"editedAt": "2026-01-16T15:00:00Z",
"locked": true
},
"def": { ... }
}

Processing Rules​

Reading​

  1. Parse $meta if present; treat absence as empty metadata
  2. Unknown fields in $meta should be preserved (forward compatibility)
  3. Unknown fields in extensions should be preserved
  4. Invalid $meta structure may be treated as a warning, not an error

Writing​

  1. Include $meta when provenance information is available
  2. Preserve existing extensions from other tools when updating
  3. Update editedAt and editedBy when modifying files
  4. Recalculate checksum if content changes

Merging​

When merging metadata from multiple sources:

/// Merge two FileMeta, preferring values from `override`
pub fn merge_meta(base: FileMeta, override: FileMeta) -> FileMeta {
FileMeta(
source: option.or(override.source, base.source),
source_range: option.or(override.source_range, base.source_range),
compiler: option.or(override.compiler, base.compiler),
generated: option.or(override.generated, base.generated),
checksum: option.or(override.checksum, base.checksum),
edited_by: option.or(override.edited_by, base.edited_by),
edited_at: option.or(override.edited_at, base.edited_at),
locked: option.or(override.locked, base.locked),
is_generated: option.or(override.is_generated, base.is_generated),
extensions: dict.merge(base.extensions, override.extensions),
)
}

Checksum Format​

Checksums use a prefixed format to identify the algorithm:

algorithm:hexdigest

Supported algorithms:

  • sha256:... (recommended)
  • sha1:... (legacy)
  • md5:... (legacy, not recommended)

Example:

{
"$meta": {
"checksum": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
}
}

Validation​

$meta validation is lenient to support forward compatibility:

CheckSeverityAction
Unknown standard fieldInfoPreserve, log
Invalid field typeWarningIgnore field, preserve raw
Invalid sourceRangeWarningIgnore field
Invalid timestamp formatWarningPreserve as string
Unknown extension namespaceNonePreserve

Security Considerations​

  • $meta should not contain secrets (API keys, credentials)
  • source paths may reveal directory structure; consider stripping in public distributions
  • extensions from untrusted sources should be treated as untrusted data
  • checksum can verify integrity but not authenticity (no signatures)

Future Considerations​

Signatures​

Digital signatures could be added for authenticity:

{
"$meta": {
"checksum": "sha256:...",
"signature": {
"algorithm": "ed25519",
"publicKey": "...",
"value": "..."
}
}
}

Compression Hints​

For large files, compression hints could guide tooling:

{
"$meta": {
"compression": {
"algorithm": "gzip",
"originalSize": 102400
}
}
}

Cross-references to related artifacts:

{
"$meta": {
"related": {
"test": "tests/domain/user-test.value.json",
"docs": "docs/domain/user.md"
}
}
}