Federation Bundle Export

Per SPRINT_8200_0014_0002.

Overview

Federation bundles enable multi-site synchronization of canonical advisory data. Each bundle contains a delta of changes since a specified cursor position, allowing incremental sync between federated Concelier instances.

Bundle Format

Bundles use a TAR archive compressed with ZStandard (ZST):

feedser-bundle-v1.zst
├── MANIFEST.json           # Bundle metadata
├── canonicals.ndjson       # Canonical advisories (one per line)
├── edges.ndjson            # Source edges (one per line)
├── deletions.ndjson        # Withdrawn/deleted canonical IDs
└── SIGNATURE.json          # DSSE envelope (optional)

MANIFEST.json

{
  "version": "feedser-bundle/1.0",
  "site_id": "site-us-west-1",
  "export_cursor": "2025-01-15T10:30:00.000Z#0042",
  "since_cursor": "2025-01-14T00:00:00.000Z#0000",
  "exported_at": "2025-01-15T10:30:15.123Z",
  "counts": {
    "canonicals": 1234,
    "edges": 3456,
    "deletions": 12,
    "total": 4702
  },
  "bundle_hash": "sha256:a1b2c3d4..."
}
FieldTypeDescription
versionstringBundle format version identifier
site_idstringIdentifier of the exporting site
export_cursorstringCursor position after this export
since_cursorstring?Cursor position from which changes were exported (null for full export)
exported_atISO8601Timestamp when bundle was created
countsobjectItem counts by type
bundle_hashstringSHA256 hash of compressed bundle content

canonicals.ndjson

Each line contains a canonical advisory record:

{"id":"uuid","cve":"CVE-2024-1234","affects_key":"pkg:npm/express@4.0.0","merge_hash":"a1b2c3...","status":"active","severity":"high","title":"..."}

edges.ndjson

Each line contains a source edge linking a canonical to its source advisory:

{"id":"uuid","canonical_id":"uuid","source":"nvd","source_advisory_id":"CVE-2024-1234","vendor_status":"affected"}

deletions.ndjson

Each line contains a deletion record for withdrawn or deleted canonicals:

{"canonical_id":"uuid","deleted_at":"2025-01-15T10:00:00Z","reason":"withdrawn"}

SIGNATURE.json

When signing is enabled, contains a DSSE envelope over the bundle hash:

{
  "payload_type": "application/vnd.stellaops.bundle-hash+json",
  "payload": "eyJidW5kbGVfaGFzaCI6InNoYTI1NjphMWIy..."}",
  "signatures": [
    {
      "keyid": "sha256:xyz...",
      "sig": "MEUCIQD..."
    }
  ]
}

API Endpoints

Export Bundle

GET /api/v1/federation/export

Exports a delta bundle for federation sync.

Query Parameters:

ParameterTypeDefaultDescription
since_cursorstringnullExport changes since this cursor (null = full export)
signbooltrueSign the bundle with Authority key
max_itemsint10000Maximum items per bundle (1-100000)
compress_levelint3ZST compression level (1-19)

Response Headers:

HeaderDescription
Content-Typeapplication/zstd
Content-Dispositionattachment; filename="feedser-bundle-{timestamp}.zst"
X-Bundle-HashSHA256 hash of bundle content
X-Export-CursorCursor position after this export
X-Items-CountTotal items in bundle

Response: Streaming ZST-compressed TAR archive.

Errors:

StatusCodeDescription
400VALIDATION_FAILEDInvalid parameter values
503FEDERATION_DISABLEDFederation is not enabled

Preview Export

GET /api/v1/federation/export/preview

Preview export statistics without creating a bundle.

Query Parameters:

ParameterTypeDefaultDescription
since_cursorstringnullPreview changes since this cursor

Response:

{
  "since_cursor": "2025-01-14T00:00:00Z#0000",
  "estimated_canonicals": 1234,
  "estimated_edges": 3456,
  "estimated_deletions": 12,
  "estimated_size_bytes": 5242880,
  "estimated_size_mb": 5.0
}

Federation Status

GET /api/v1/federation/status

Get federation configuration status.

Response:

{
  "enabled": true,
  "site_id": "site-us-west-1",
  "default_compression_level": 3,
  "default_max_items": 10000
}

CLI Commands

Export Bundle

stella feedser bundle export [options]

Options:

OptionShortDefaultDescription
--since-cursor-cnullExport changes since cursor
--output-ostdoutOutput file path
--sign-strueSign bundle with Authority key
--compress-level-l3ZST compression level (1-19)
--max-items-m10000Maximum items per bundle
--jsonfalseOutput metadata as JSON

Examples:

# Full export to file
stella feedser bundle export -o ./bundle.zst

# Delta export since cursor
stella feedser bundle export -c "2025-01-14T00:00:00Z#0000" -o ./delta.zst

# Export without signing (for testing)
stella feedser bundle export --sign=false -o ./unsigned.zst

# High compression for archival
stella feedser bundle export -l 19 -o ./archived.zst

Preview Export

stella feedser bundle preview [options]

Options:

OptionShortDescription
--since-cursor-cPreview changes since cursor
--jsonOutput as JSON

Example:

stella feedser bundle preview -c "2025-01-14T00:00:00Z#0000"

Configuration

Federation is configured in concelier.yaml:

Federation:
  Enabled: true
  SiteId: "site-us-west-1"
  DefaultCompressionLevel: 3
  DefaultMaxItems: 10000
  RequireSignature: true
SettingTypeDefaultDescription
EnabledboolfalseEnable federation endpoints
SiteIdstring“default”Identifier for this site
DefaultCompressionLevelint3Default ZST compression level
DefaultMaxItemsint10000Default max items per bundle
RequireSignaturebooltrueRequire bundle signatures

Cursor Format

Cursors encode a timestamp and sequence number:

{ISO8601}#{sequence}

Example: 2025-01-15T10:30:00.000Z#0042

Cursors are opaque to consumers and should be passed through unchanged.

Determinism

Bundles are deterministic:

Security