Skip to content

feat(sbom): implement v1 dependency extraction from build.zig.zon - #5

Merged
Eugene3dotdev merged 4 commits into
mainfrom
feat/sbom-v1-deps
Jun 12, 2026
Merged

Eugene3dotdev merged 4 commits into
mainfrom
feat/sbom-v1-deps

Conversation

@Eugene3dotdev

Copy link
Copy Markdown
Owner

Closes #3.

Summary

Replaces the v0 stubs (findStructField, findStringFieldInStruct) with real std.zig.Ast extraction using the stdlib's own zon idioms — rootDecls()[0] zon root, fullStructInit, and the firstToken(field) − 2 field-name token (same pattern as std/zon/parse.zig:1105):

  • one CycloneDX component per declared dependency, carrying name + .hash + .url; path-only deps appear with empty hash/url
  • fail-closed guard retained and regression-tested: a .dependencies value that is not a struct init still raises IncompleteSbom
  • allocator made explicit on findStructField (caller frees entries); stub-era wording removed from SbomError doc and the refusal log

Stacked on fix/r6-cross-plan-gaps (#4) — retarget to main automatically when #4 merges.

Test plan

  • TDD red→green: zig test scripts/emit-sbom.zig 4/4 (extraction, fail-closed, no-deps, JSON escaping)
  • e2e: zig run scripts/emit-sbom.zig -- build.zig.zon emits valid CycloneDX for the repo's own manifest
  • native + x86_64-windows-msvc compile
  • bun scripts/verify-commit.ts OK (fmt, ast-check, zig build test, API baseline)
  • bun test 15/15

…yList)

WHY: Cross-validation against the sibling-repo revision plans (synthfq,
gitstore-cli) surfaced two 0.16-drift items in this repo that CodeRabbit's
PR #1 threads never flagged, so R5 left them untouched. Both are the
exact drift classes this template exists to police.

WHAT:
- doc/TIGER_STYLE_ZIG.md §1.4: argsAlloc row no longer claims the API is
  "unchanged"; right column now shows the Juicy Main pattern
  init.minimal.args.toSlice(init.arena.allocator()).
- scripts/zig-fitness.zig (stack walk + escapeJsonString) and
  scripts/emit-sbom.zig (escapeJsonString): std.array_list.Managed
  replaced with unmanaged std.ArrayList (.empty, append(gpa, ...),
  deinit(gpa), toOwnedSlice(gpa)).

IMPACT: docs + aux scripts only; no public API change (baseline OK);
scripts/ now has zero std.array_list.Managed occurrences.

VALIDATION: zig-fitness + emit-sbom compile for native and
x86_64-windows-msvc; verify-commit OK (fmt, ast-check, zig build test,
API baseline); bun test 15/15.
Copilot AI review requested due to automatic review settings June 12, 2026 11:23
@coderabbitai

coderabbitai Bot commented Jun 12, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

@EugOT, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 4 hours, 58 minutes, and 31 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more credits in the billing tab to continue.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: d6eb1b0a-1f07-4697-811f-27feeab03062

📥 Commits

Reviewing files that changed from the base of the PR and between f3158b0 and b5ce2e6.

📒 Files selected for processing (1)
  • scripts/emit-sbom.zig
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/sbom-v1-deps

Comment @coderabbitai help to get the list of available commands and usage tips.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

https://github.com/EugOT/claude-zig-quality/blob/3fd4139ccae327863940e1657afa2c2d11ae87a0/scripts/emit-sbom.zig#L163
P2 Badge Strip Zig multihash before emitting SHA-256

When a URL dependency has the normal Zig .hash value, this emits that value as a CycloneDX SHA-256 digest, but Zig hashes include the multihash prefix (1220 + the 64 hex SHA-256 bytes). The resulting 68-hex-character content is not a valid CycloneDX SHA-256 hash, and path-only dependencies currently emit an empty hash the same way, so verify-release can write an SBOM that schema validators reject as soon as dependencies are present.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Implements v1 SBOM dependency extraction for build.zig.zon by replacing the prior stubbed dependency discovery with real std.zig.Ast-based traversal, and updates/expands inline tests to cover the new behavior and the fail-closed guard.

Changes:

  • Implemented findStructField / findStringFieldInStruct using .zon AST struct-init idioms to enumerate .dependencies.
  • Kept the “fail closed” behavior for declared-but-unwalkable .dependencies shapes and added a regression test for non-struct .dependencies.
  • Updated tests to validate emitted components for extracted dependencies.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread scripts/emit-sbom.zig
Comment thread scripts/emit-sbom.zig
Comment thread scripts/emit-sbom.zig Outdated
Comment thread scripts/emit-sbom.zig Outdated
Comment thread scripts/emit-sbom.zig Outdated
Comment thread scripts/emit-sbom.zig Outdated
WHY: closes claude-zig-quality#3. The v0 emitter stubbed dependency
extraction (findStructField returned null), so any manifest declaring
.dependencies failed closed and no SBOM with components could ever be
published.

WHAT: real std.zig.Ast extraction using the stdlib's own zon idioms
(rootDecls()[0] zon root, fullStructInit, firstToken(field)-2 name
token — same as std/zon/parse.zig):
- findStructField walks .dependencies and returns one DepEntry per
  declared dep (caller-freed slice; allocator now explicit).
- findStringFieldInStruct extracts .url/.hash strings from each entry.
- Fail-closed guard retained: a .dependencies value that is not a
  struct init still raises IncompleteSbom (new regression test).
- Stub-era wording removed from SbomError doc and refusal log.

IMPACT: emit-sbom now publishes CycloneDX components for declared
dependencies; path-only deps appear with empty hash/url. No public
API change (baseline OK).

VALIDATION: TDD red->green; zig test scripts/emit-sbom.zig 4/4
(extraction, fail-closed, no-deps, JSON escaping); e2e run on the
repo's own build.zig.zon emits valid CycloneDX; native +
x86_64-windows-msvc compile; verify-commit OK; bun test 15/15.
@Eugene3dotdev

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 12, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@Eugene3dotdev
Eugene3dotdev changed the base branch from fix/r6-cross-plan-gaps to main June 12, 2026 16:32
@Eugene3dotdev

Copy link
Copy Markdown
Owner Author

Verified all 5 Copilot picks are addressed at HEAD (they were filed pre-refactor and are now marked outdated):

  • findStructField guards empty rootDecls() with if (roots.len == 0) return null; → no out-of-bounds on degenerate .zon.
  • All three field-name lookups route through fieldNameToken, which guards the firstToken(...) - 2 underflow twice: if (first_tok < 2) return null; and the name_tok >= token_tags.len bounds check (plus an .identifier tag check).
  • The path-only-deps test is regression-proof: asserts "url": "../other" is emitted and that "content": "" / "url": "" are absent.

Build: 7/7 steps, 16/16 tests pass on mise x zig@0.16.0. CodeRabbit + Kilo checks SUCCESS. Resolving the outdated threads and merging.

@Eugene3dotdev
Eugene3dotdev merged commit a6ff0f1 into main Jun 12, 2026
2 checks passed
@Eugene3dotdev
Eugene3dotdev deleted the feat/sbom-v1-deps branch June 12, 2026 16:48
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.

emit-sbom v1: implement SBOM dependency extraction from build.zig.zon

2 participants