Skip to content

feat: wire storage backend into attestation generator#143

Merged
mlieberman85 merged 4 commits into
kusari-oss:mainfrom
Marc-cn:feature/storage-wiring
Apr 15, 2026
Merged

feat: wire storage backend into attestation generator#143
mlieberman85 merged 4 commits into
kusari-oss:mainfrom
Marc-cn:feature/storage-wiring

Conversation

@Marc-cn
Copy link
Copy Markdown
Collaborator

@Marc-cn Marc-cn commented Apr 1, 2026

Summary

Follow-up to #139 as requested, hooks the storage backend into the attestation generator so it's used in practice, not just a standalone module.

Type of Change

  • New feature (non-breaking change adding functionality)

Framework Changes Checklist

  • Updated framework spec if behavior changed
  • Ran uv run python scripts/validate_sync.py --verbose and it passes
  • Ran uv run python scripts/generate_docs.py and committed any doc changes

Control/TOML Changes Checklist

Not applicable — no controls or TOML modified in this PR.

Testing

  • Tests pass locally
  • Added tests for new functionality
  • Linting passes

What was built

Added storage_config parameter to generate_attestation_from_results() in the attestation generator. After building the attestation, it calls get_backend(storage_config).store_attestation() before saving to file.

  • If storage succeeds, the reference is logged
  • If storage fails for any reason, it logs a warning and continues, the file save still happens, nothing breaks
  • If no storage_config is provided, defaults to FileBackend (no behaviour change)

Usage

generate_attestation_from_results(
    audit_result=result,
    storage_config={"backend": "archivista", "archivista_url": "http://localhost:8082"}
)

Additional Notes

  • 31 tests passing (4 new wiring tests + 27 existing storage tests)
  • Backwards compatible, existing callers with no storage_config are unaffected

@mlieberman85
Copy link
Copy Markdown
Contributor

Review: Rebased after #139 merge — tests pass, issues remain

Rebased onto upstream/main. Git automatically dropped the duplicate storage backends commit (already on main via #139). The PR is now a clean 2-file diff: generator.py (+18 lines) and test_attestation_storage.py (+97 lines). All 1246 tests pass, lint is clean.

Issues

Bug 1: Storage always runs even when not configured (generator.py:127-138)

When storage_config=None (the default), get_backend(None) returns a FileBackend which writes the attestation to .darnit/attestations/ — creating a new directory and duplicate file on every attestation generation. This is a silent behavior change for all existing callers.

# generator.py:127 — should be guarded
try:
    from darnit.storage.backends import get_backend
    storage = get_backend(storage_config)  # Returns FileBackend when None

Fix: wrap the entire storage block with if storage_config is not None:.

Bug 2: json.loads(output) re-parses just-serialized JSON (generator.py:133)

The attestation dict was just serialized via json.dumps() a few lines above, then immediately re-parsed. Should pass the unsigned or signed dict directly instead of round-tripping through JSON.

Bug 3: Hardcoded GitHub URL (generator.py:126)

repo_url = f"https://github.com/{audit_result.owner}/{audit_result.repo}" assumes GitHub hosting. The framework already has detect_forge() which returns the hosting platform — this should use that or construct the URL from git remote data.

Note on test patching: The tests patch darnit.storage.backends.get_backend rather than patching at the import site in the generator. This works because the generator does a lazy from darnit.storage.backends import get_backend inside the try block each time, so it resolves from the original module where the patch lives. This is correct but fragile — if the import is ever moved to module level, the patch would break. Consider patching darnit_baseline.attestation.generator.get_backend instead once the import is hoisted.

Verdict

Bug #1 (storage always runs) should be fixed before merge — it creates unwanted side effects for existing callers. Bugs #2 and #3 are minor and can be follow-ups.

@mlieberman85 mlieberman85 force-pushed the feature/storage-wiring branch from 32b2a37 to b3ee1e0 Compare April 4, 2026 18:23
Comment thread packages/darnit-baseline/src/darnit_baseline/attestation/generator.py Outdated
Comment thread packages/darnit-baseline/src/darnit_baseline/attestation/generator.py Outdated
Comment thread packages/darnit-baseline/src/darnit_baseline/attestation/generator.py Outdated
storage_ref = storage.store_attestation(
repo_url=repo_url,
commit=audit_result.commit,
attestation=unsigned,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So where does the signed attestation end up going?

storage_config={"backend": "memory"},
)

mock_logger.info.assert_called_once()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will fail because it logs on file save and logs on storage ref

The generator emits two logger.info calls (file save + storage backend),
but the test was asserting only one. Verify the storage backend log is
present without requiring it to be the only call.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@mlieberman85
Copy link
Copy Markdown
Contributor

LGTM

@mlieberman85 mlieberman85 merged commit 0ee88b6 into kusari-oss:main Apr 15, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants