Architecture Decision Record

ADR-0024: Artifact Upload and Fact Append Remain Separate Core Operations

Status: Accepted · Date: 2026-03-06

Status: Accepted

Date: 2026-03-06

Context

BSFG stores large artifacts out-of-band and references them from facts. This creates a design question: should the boundary contract expose a single convenience operation that both uploads an artifact and appends the referencing fact, or should these remain separate primitives?

The architecture already distinguishes:

The decision must preserve conceptual clarity without making common client flows unnecessarily awkward.

Options Considered

Option Description Benefits Drawbacks
Single combined primitive only Expose one core RPC that uploads the artifact and appends the fact in one operation.

|

| | Best-effort wrapper as the only public API | Expose only a convenience wrapper that internally calls object storage and fact append separately. |

|

| | Separate core operations (Selected) | Keep PutObject and AppendFact as distinct primitives; allow wrappers only as optional conveniences outside the core contract. |

|

| | Artifact-first implicit append | Make object upload itself create a fact automatically. |

|

|

Decision

BSFG keeps artifact upload and fact append as separate core operations.

PutObject(blob)   -> object store durability
AppendFact(ref)  -> semantic history

The canonical boundary contract therefore remains:

AppendFact
FetchFacts
ConfirmReceipt
PutObject

A fact that references an artifact is appended only after the artifact reference is known. The reference must include sufficient integrity and retrieval metadata, such as bucket, key, digest, size, and media type.

Convenience wrappers such as AppendWithAttachment may exist in higher-level SDKs or service facades, but they are not part of the core BSFG architectural primitive.

Consequences

Benefits:

Tradeoffs: