bus-attachments — evidence storage and attachment metadata (SDD)
bus-attachments — evidence storage and attachment metadata
Introduction and Overview
Bus Attachments stores evidence files and maintains attachment metadata as schema-validated repository data so other modules can link to evidence without embedding file paths directly in domain datasets.
Requirements
FR-ATT-001 Attachment metadata registry. The module MUST write stable attachment identifiers and immutable metadata to attachments.csv with schema validation. Acceptance criteria: each added attachment has a stable identifier and hash metadata, and invalid inputs fail without modifying datasets.
FR-ATT-002 CLI surface for evidence registration. The module MUST provide commands to initialize, add, and list attachments. Acceptance criteria: init, bus attachments add, and bus attachments list are available and emit deterministic outputs.
FR-ATT-003 Init behavior. The module MUST provide an init command that creates the attachments metadata dataset and schema when they are absent. When they already exist in full, init MUST print a warning to standard error and exit 0 without modifying anything. When they exist only partially, init MUST fail with a clear error and not write any file (see bus-init FR-INIT-004). Acceptance criteria: bus attachments init is available; idempotent and partial-state behavior as specified.
FR-ATT-004 Attachment link graph and filter/audit queries. The module MUST provide deterministic attachment-to-resource linking and list/query capabilities: filters by bank row/voucher/invoice/date/unlinked status, reverse-link graph output, and strict audit flags (fail-if-unlinked, fail-if-missing-kind). Acceptance criteria: link-many workflows are supported (add once, then link multiple resources), list filters are deterministic, graph output is machine-readable, and strict flags can produce non-zero exit for CI/audit gates.
NFR-ATT-001 Auditability. Attachment metadata MUST remain in the repository even if files are stored outside Git. Acceptance criteria: metadata rows are retained and list outputs remain deterministic.
NFR-ATT-002 Path exposure via Go library. The module MUST expose a Go library API that returns the workspace-relative path(s) to its owned data file(s) (attachments metadata CSV and schema). Other modules that need read-only access to the attachment metadata raw file(s) MUST obtain the path(s) from this module’s library, not by hardcoding file names. The API MUST be designed so that future dynamic path configuration can be supported without breaking consumers. Acceptance criteria: the library provides path accessor(s) for the attachments dataset; consumers use these accessors for read-only access; no consumer hardcodes attachments.csv outside this module.
System Architecture
Bus Attachments owns the repository-root attachments metadata dataset and manages references to files stored under a predictable directory structure. It integrates with invoices, journal entries, bank data, and reconciliation by providing stable attachment identifiers.
Key Decisions
KD-ATT-001 Attachment evidence is recorded as repository data. Attachment metadata remains in the workspace datasets for the full retention period.
KD-ATT-002 Attachments are a special case for file layout. Evidence files are stored under a dedicated subdirectory ./attachments/yyyy/mm/yyyymmdd-filename... (relative to the workspace root), where yyyy is the four-digit year, mm is the two-digit month, and the filename is prefixed with an eight-digit date. The metadata dataset and schema remain at the workspace root; only the evidence files use this subdirectory.
KD-ATT-003 Path exposure for read-only consumption. The module exposes path accessors in its Go library so that other modules can resolve the location of the attachments metadata dataset for read-only access. Write access and all attachment business logic remain in this module.
Component Design and Interfaces
Interface IF-ATT-001 (module CLI). The module exposes bus attachments with subcommands init, add, link, and list and follows BusDK CLI conventions for deterministic output and diagnostics.
The init command creates baseline attachments metadata and links datasets/schemas (attachments.csv, attachments.schema.json, attachment-links.csv, attachment-links.schema.json) when they are absent. If all already exist and are consistent, init prints a warning to standard error and exits 0 without modifying anything. If the data exists only partially, init fails with a clear error to standard error, does not write any file, and exits non-zero (see bus-init FR-INIT-004).
The add command accepts a positional file path plus a description parameter. Documented parameters are <file> as a positional argument and --desc <text> for the attachment description. The link command accepts either <attachment_id> or deterministic replay-safe selectors (--path, --desc-exact, --source-hash) plus target parameters (--kind/--id, or shortcut selectors such as --bank-row, --voucher, --invoice) and appends deterministic link rows to attachment-links.csv. Selector resolution must be deterministic: zero matches and multiple matches are hard errors. The list command supports deterministic filters and reverse-link graph output, with strict audit flags for CI gating.
Interface IF-ATT-002 (path accessors, Go library). The module exposes Go library functions that return the workspace-relative path(s) to its owned data file(s) (attachments metadata CSV/schema and attachment-links CSV/schema). Given a workspace root path, the library returns the path(s); resolution MUST allow future override from workspace or data package configuration. Other modules use these accessors for read-only access only; all writes and attachment logic remain in this module.
Usage examples:
bus attachments add tmp/INV-1001.pdf --desc "Invoice INV-1001 (PDF)"
bus attachments link <attachment_id> --invoice INV-1001
bus attachments link --source-hash <sha256> --bank-row 27201 --if-missing
bus attachments list
Data Design
The module reads and writes attachments.csv and attachment-links.csv in the repository root with beside-the-table schema files. Master data (metadata + links datasets and schemas) lives in the workspace root only. Evidence files are stored under ./attachments/yyyy/mm/yyyymmdd-filename... — for example attachments/2026/01/20260115-INV-1001.pdf — where yyyy is the four-digit year, mm is the two-digit month, and the filename begins with an eight-digit date. This is the only BusDK layout that places operational files in a subdirectory; the path is deterministic so metadata can reference it reliably. Each attachment_id is a standard UUID string in canonical form so integrations can generate or validate identifiers without guessing; the expected representation is lowercase hex with hyphens in 8-4-4-4-12 grouping.
Other modules that need read-only access to the attachments metadata dataset MUST obtain the path from this module’s Go library (IF-ATT-002). All writes and attachment-domain logic remain in this module.
Assumptions and Dependencies
Bus Attachments depends on the workspace layout and schema conventions and assumes the file path provided exists and is readable. Missing files or inaccessible paths result in deterministic diagnostics.
Security Considerations
Attachment files may contain sensitive evidence and should be protected by repository access controls. Hashes and metadata are stored to keep the audit trail verifiable.
Observability and Logging
Command results are written to standard output, and diagnostics are written to standard error with deterministic references to dataset paths and identifiers.
Error Handling and Resilience
Invalid usage exits with a non-zero status and a concise usage error. Missing files or schema violations exit non-zero without modifying datasets.
Testing Strategy
Unit tests cover metadata validation and hashing, and command-level tests exercise add and list against fixture workspaces with sample files.
Deployment and Operations
Not Applicable. The module ships as a BusDK CLI component and relies on the standard workspace layout.
Migration/Rollout
Not Applicable. Schema evolution is handled through the standard schema migration workflow for workspace datasets.
Risks
Not Applicable. Module-specific risks are not enumerated beyond the general need for deterministic and audit-friendly evidence handling.
Glossary and Terminology
Attachment: an evidence file registered in attachments.csv and referenced by stable identifier.
Attachment metadata: immutable details such as filename, media type, and hash.