---
title: "SSOT Sync Provenance Schema v1.0.0"
description: "Audit trail metadata for SSOT sync operations"
author: "Pipeline Architect"
date: "2025-10-28"
last_updated: "2025-10-28"
status: "stable"
tags: ["content", "ssot", "provenance", "audit"]
---

# SSOT Sync Provenance Schema v1.0.0

## Purpose

The SSOT Sync Provenance schema provides standardized metadata for tracking the origin and state of synced content from Single Source of Truth (SSOT) repositories. This enables:

- **Audit trails**: Know exactly which SSOT version/commit was synced
- **Reproducibility**: Recreate exact sync state for debugging
- **Dependency tracking**: Understand which SSOTs a repository depends on
- **Dirty state detection**: Identify when synced content came from uncommitted changes

## Schema Location

- **File**: `ssot-provenance.schema.json`
- **$id**: `https://github.com/fulmenhq/crucible/schemas/content/ssot-provenance/v1.0.0/ssot-provenance.schema.json`
- **Draft**: JSON Schema Draft 2020-12

## Usage

### Generated By

This file is automatically generated by SSOT sync tools (e.g., goneat) during sync operations. Consumers should **never manually edit** provenance files.

**Typical location**: `.goneat/ssot/provenance.json` in repositories consuming SSOT content

### Consumed By

- **Helper libraries** (gofulmen, pyfulmen, tsfulmen) - Read provenance to display version info
- **CI/CD pipelines** - Validate SSOT versions and detect dirty syncs
- **Development tools** - Show developers which SSOT versions they're using
- **Audit systems** - Track SSOT dependency chains across ecosystem

## Structure

### Top-Level Fields

| Field          | Type   | Required | Description                                 |
| -------------- | ------ | -------- | ------------------------------------------- |
| `schema`       | object | ✅       | Schema identifier (name, version, URL)      |
| `generated_at` | string | ✅       | ISO 8601 timestamp of provenance generation |
| `sources`      | array  | ✅       | Array of source metadata (min 1 item)       |

### Schema Identifier

```json
{
  "schema": {
    "name": "goneat.ssot.provenance",
    "version": "v1",
    "url": "https://github.com/fulmenhq/crucible/schemas/content/ssot-provenance/v1.0.0/ssot-provenance.schema.json"
  }
}
```

### Source Metadata

Each source in the `sources` array represents one SSOT repository that was synced.

| Field            | Type    | Required | Description                                     |
| ---------------- | ------- | -------- | ----------------------------------------------- |
| `name`           | string  | ✅       | Human-readable source name                      |
| `slug`           | string  | ✅       | URL-safe slug (lowercase alphanumeric + dashes) |
| `method`         | enum    | ✅       | Sync method used                                |
| `repo_url`       | string  | ❌       | Repository URL (e.g., GitHub)                   |
| `local_path`     | string  | ❌       | Local filesystem path for sync                  |
| `ref`            | string  | ❌       | Git ref (branch/tag) used                       |
| `commit`         | string  | ❌       | Full 40-character Git commit SHA                |
| `dirty`          | boolean | ❌       | Whether source had uncommitted changes          |
| `dirty_reason`   | enum    | ❌       | Reason for dirty status                         |
| `version_file`   | string  | ❌       | Version file name (e.g., "VERSION")             |
| `version`        | string  | ❌       | Version string from version file                |
| `version_source` | string  | ❌       | Source of version info                          |
| `outputs`        | object  | ❌       | Map of asset type → destination path            |

### Sync Methods

- `local_path` - Synced from local filesystem path
- `git_ref` - Synced from Git branch/ref
- `git_tag` - Synced from Git tag
- `archive` - Synced from archive file

### Dirty Reasons

- `worktree-dirty` - Git working tree has uncommitted changes
- `non-git` - Source is not a Git repository
- `no-head` - Git repository has no HEAD (empty repo)
- `no-worktree` - Git repository has no working tree (bare repo)
- `status-error` - Error checking Git status

## Example

```json
{
  "schema": {
    "name": "goneat.ssot.provenance",
    "version": "v1",
    "url": "https://github.com/fulmenhq/crucible/schemas/content/ssot-provenance/v1.0.0/ssot-provenance.schema.json"
  },
  "generated_at": "2025-10-28T18:59:49.509077Z",
  "sources": [
    {
      "name": "crucible",
      "slug": "crucible",
      "method": "local_path",
      "repo_url": "https://github.com/fulmenhq/crucible",
      "local_path": "../crucible",
      "ref": "main",
      "commit": "14540342ad9defcedcd4a2f9c6a167bd10f7cb5d",
      "dirty": false,
      "version_file": "VERSION",
      "version": "2025.10.3",
      "version_source": "VERSION",
      "outputs": {
        "config": "config/crucible-py",
        "doc": "docs/crucible-py",
        "metadata": ".crucible/metadata",
        "schema": "schemas/crucible-py"
      }
    }
  ]
}
```

## Integration Patterns

### Reading Provenance in Helper Libraries

```python
# pyfulmen example
from pyfulmen.crucible import get_provenance

provenance = get_provenance()
for source in provenance["sources"]:
    print(f"{source['name']}: {source['version']} ({source['commit'][:7]})")
    if source.get("dirty"):
        print(f"  ⚠️  WARNING: Synced from dirty source ({source['dirty_reason']})")
```

```go
// gofulmen example
import "github.com/fulmenhq/gofulmen/crucible"

prov, err := crucible.GetProvenance()
if err != nil {
    log.Fatal(err)
}

for _, src := range prov.Sources {
    log.Printf("%s: %s (%s)", src.Name, src.Version, src.Commit[:7])
    if src.Dirty {
        log.Printf("  ⚠️  WARNING: Synced from dirty source (%s)", src.DirtyReason)
    }
}
```

### CI/CD Validation

```yaml
# .github/workflows/validate-ssot.yml
- name: Check SSOT Provenance
  run: |
    if jq -e '.sources[] | select(.dirty == true)' .goneat/ssot/provenance.json; then
      echo "❌ ERROR: SSOT synced from dirty sources"
      exit 1
    fi
```

## Version History

- **v1.0.0** (2025-10-28): Initial stable release
  - Migrated from goneat internal schema to Crucible SSOT
  - Updated $id to Crucible location
  - Added comprehensive documentation

## Related Schemas

- [Embed Manifest](../../embed-manifest/v1.1.0/README.md) - Content bundling metadata
- [Binary Embed Manifest](../../binary-embed-manifest/v1.0.0/README.md) - Binary asset bundling
- [Sync Keys Schema](../../../config/sync-keys.schema.yaml) - SSOT sync configuration

## Migration from goneat

**For goneat maintainers**: After this schema is synced to goneat:

1. Update imports to use Crucible schema location
2. Update schema URL in generated provenance files
3. Remove `schemas/ssot/provenance.v1.json` from goneat repository
4. Add sync configuration to pull this schema from Crucible

**For consumers**: No action required - provenance files remain at `.goneat/ssot/provenance.json`
