Skip to content

feat: bound public API surface + fix broken CLI surface (OSS P0)#47

Merged
boorad merged 6 commits intomainfrom
fix/oss-p0-surface
May 5, 2026
Merged

feat: bound public API surface + fix broken CLI surface (OSS P0)#47
boorad merged 6 commits intomainfrom
fix/oss-p0-surface

Conversation

@jhawlwut
Copy link
Copy Markdown

@jhawlwut jhawlwut commented May 4, 2026

What

Addresses the two code-side P0 items from the pre-release panel review that block flipping the repo public.

PUBLIC-1 — Bound the public crate API surface (Cargo.toml, src/lib.rs, src/main.rs)

Every module was pub, crystallising the entire codebase as a semver commitment the moment the repo goes public. This commit draws a clear line:

Module Visibility Reason
cli, error, types, rules, rego always pub stable contract
commands, logging always mod (private) binary internals; reached via lib::run
config, deep, mcp, output, scanner pub only with --features unstable implementation details; no semver commitment

A new top-level pub fn run(cli: Cli) -> Result<()> replaces the three-import dispatch pattern in main.rs, which is now a four-line shim.

PUBLIC-2 — Fix advertised-but-broken CLI surface (src/cli.rs, src/commands/scan.rs, src/error.rs, src/scanner/parser.rs)

Two surfaces that parse cleanly then fail at runtime:

SARIF: --format sarif was accepted by clap, then returned ZiftError::General("SARIF output not yet implemented"). Removed OutputFormat::Sarif entirely; the match is now exhaustive over Text and Json. SARIF can land as feat: add SARIF output in v0.2. AGENTS.md and docs/DESIGN.md updated.

UnsupportedLanguage: get_language() returned ZiftError::General(String) for CSharp/Kotlin/Ruby/Php. Replaced with a new typed variant ZiftError::UnsupportedLanguage(Language) so callers can pattern-match and the message is consistent across all surfaces.

What's NOT in this PR (handled separately)

  • PUBLIC-3: CODEOWNERS team staffing + branch protection — GitHub admin config, no code change needed.
  • PUBLIC-4: agent_cmd stderr warning + .gitignore entry — planned for v0.1.x.
  • All P1 items from the panel report.

Test plan

  • CI passes (cargo test, cargo clippy -- -D warnings)
  • zift --help no longer shows sarif as a valid format option
  • zift --format sarif . no longer compiles (variant removed)
  • Error message for zift scan --language csharp . now reads "csharp is not yet supported in v0.1; support is planned for v0.2"
  • cargo build --features unstable exposes config, deep, mcp, output, scanner modules to external consumers

Summary by CodeRabbit

  • New Features

    • Added an unstable feature flag to opt into additional (non-stable) APIs
  • Refactor

    • Removed SARIF as a selectable output format; CLI now supports text and JSON only
    • Reduced the crate's stable public API surface — several modules are opt-in under unstable
    • Consistent startup behavior and unified error reporting on failure
    • Improved error reporting for unsupported languages
  • Chores

    • Suppressed various dead-code warnings to reduce noise

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 4, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR removes SARIF as a CLI output option, adds an unstable Cargo feature to gate internal modules, tightens crate visibility, adds ZiftError::UnsupportedLanguage(Language), updates scanner tests, simplifies main to call zift::run(...), and updates docs and minor lint suppressions.

Changes

Public surface, CLI, command flow, and errors

Layer / File(s) Summary
Feature Flag
Cargo.toml
Adds [features] unstable = [] with comments describing opt-in exposure of internal modules.
Crate Surface / Docs
src/lib.rs
Restricts stable public modules to cli, error, rego, rules, types; makes commands and logging private; gates config, deep, mcp, output, scanner as pub only under feature = "unstable"; expands crate-level docs.
CLI enum
src/cli.rs
Removes OutputFormat::Sarif, leaving only Text and Json.
Scan command
src/commands/scan.rs
Removes SARIF pre-check and Sarif match arm; execute now matches only Text and Json.
Error type
src/error.rs
Adds ZiftError::UnsupportedLanguage(Language) variant and imports Language.
Scanner behavior & tests
src/scanner/parser.rs
get_language returns ZiftError::UnsupportedLanguage(lang) for unsupported languages; tests updated to assert that variant and import ZiftError.
Application wiring
src/main.rs
Inlines startup to call zift::run(Cli::parse()); removes local run helper; prints error and exits on failure.
Documentation
docs/DESIGN.md, AGENTS.md
Removes sarif from --format docs and Architecture Output bullet; notes SARIF planned for v0.2.
Lint/noise suppressions
src/deep/candidate.rs, src/mcp/*.rs, src/mcp/server.rs
Adds #[allow(dead_code)] attributes to suppress warnings for test/debug-only fields and reserved protocol/error variants.

Sequence Diagram(s)

sequenceDiagram
    participant CLI as CLI (args)
    participant Main as main.rs
    participant Lib as zift::run
    participant Commands as commands::dispatch
    participant Scanner as scanner::parser
    CLI->>Main: Cli::parse()
    Main->>Lib: zift::run(cli)
    Lib->>Commands: dispatch "scan"
    Commands->>Scanner: get_language / parse_source
    alt supported
        Scanner-->>Commands: Language (ok)
    else unsupported
        Scanner-->>Commands: UnsupportedLanguage error
    end
    Commands-->>Lib: command Result
    Lib-->>Main: return Result
    Main-->>CLI: print error & exit / success
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • EnforceAuth/zift#48: Touches src/deep/candidate.rs (related edits around Candidate).
  • EnforceAuth/zift#41: Also modifies AGENTS.md/architecture output text (related documentation change).
  • EnforceAuth/zift#22: Prior work on gating/exporting deep module (related to unstable feature gating).

Poem

🐰 I hop through crates and tidy doors,
SARIF shelved till later shores,
I name the langs that cannot play,
Main hands run and hops away,
A neat little garden, safe and warm.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects the two main changes: bounding the public API surface and fixing the broken CLI surface (SARIF removal).
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (4)
  • PUBLIC-1: Request failed with status code 401
  • PUBLIC-2: Request failed with status code 401
  • PUBLIC-3: Request failed with status code 401
  • PUBLIC-4: Request failed with status code 401

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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

Copy link
Copy Markdown

@amazon-q-developer amazon-q-developer Bot left a comment

Choose a reason for hiding this comment

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

This PR successfully addresses the pre-release P0 items for making the repository public. The changes are well-implemented and achieve the stated objectives:

Key Changes Reviewed:

  • API surface control: The unstable feature flag pattern correctly restricts internal modules while maintaining backward compatibility for stable APIs
  • Simplified entry point: The new lib::run() function provides a clean public interface
  • SARIF removal: Properly removes the unimplemented SARIF format from CLI and command execution
  • Error handling: The new UnsupportedLanguage error variant provides better type safety and consistent error messages

Summary:
All changes function correctly and no blocking issues were identified. The implementation follows Rust best practices and successfully prepares the codebase for public release.


You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/scanner/parser.rs (1)

19-20: ⚡ Quick win

Add a regression assertion for the typed unsupported-language error.

Now that this path returns ZiftError::UnsupportedLanguage, the test should assert that exact variant (not just is_err()), so this contract doesn’t regress back to generic errors.

Suggested test tightening
 #[test]
 fn unsupported_language_returns_error() {
-    assert!(get_language(Language::CSharp, false).is_err());
+    let err = get_language(Language::CSharp, false).unwrap_err();
+    assert!(matches!(err, ZiftError::UnsupportedLanguage(Language::CSharp)));
     assert!(!is_language_supported(Language::CSharp));
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/scanner/parser.rs` around lines 19 - 20, Update the test that currently
only asserts is_err() to assert the exact error variant
ZiftError::UnsupportedLanguage; call the parser function used in the test and
replace the generic is_err() check with either assert!(matches!(result,
Err(ZiftError::UnsupportedLanguage(_)))) or an explicit pattern match (e.g., if
let Err(ZiftError::UnsupportedLanguage(lang)) = result { /* optional check on
lang */ } else { panic!("expected UnsupportedLanguage") }), ensuring the test
imports or references ZiftError::UnsupportedLanguage so the contract doesn't
regress.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/error.rs`:
- Around line 30-31: The error message on the UnsupportedLanguage variant
hardcodes a release version; update the message to be version-agnostic by
replacing the #[error("{0} is not yet supported in v0.1; support is planned for
v0.2")] attribute on UnsupportedLanguage(Language) with a neutral text (e.g.,
"{0} is not yet supported") or a message that points to docs/changelog for
roadmap, so the enum variant UnsupportedLanguage and its #[error(...)]
annotation no longer reference specific version numbers.

---

Nitpick comments:
In `@src/scanner/parser.rs`:
- Around line 19-20: Update the test that currently only asserts is_err() to
assert the exact error variant ZiftError::UnsupportedLanguage; call the parser
function used in the test and replace the generic is_err() check with either
assert!(matches!(result, Err(ZiftError::UnsupportedLanguage(_)))) or an explicit
pattern match (e.g., if let Err(ZiftError::UnsupportedLanguage(lang)) = result {
/* optional check on lang */ } else { panic!("expected UnsupportedLanguage") }),
ensuring the test imports or references ZiftError::UnsupportedLanguage so the
contract doesn't regress.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: cb61848d-8de0-48c9-afa7-8c8e57dc186a

📥 Commits

Reviewing files that changed from the base of the PR and between e0b59c6 and dae0e21.

📒 Files selected for processing (9)
  • AGENTS.md
  • Cargo.toml
  • docs/DESIGN.md
  • src/cli.rs
  • src/commands/scan.rs
  • src/error.rs
  • src/lib.rs
  • src/main.rs
  • src/scanner/parser.rs
💤 Files with no reviewable changes (2)
  • src/cli.rs
  • src/commands/scan.rs

Comment thread src/error.rs Outdated
@boorad boorad changed the title feat!: bound public API surface + fix broken CLI surface (OSS P0) feat: bound public API surface + fix broken CLI surface (OSS P0) May 4, 2026
@jhawlwut
Copy link
Copy Markdown
Author

jhawlwut commented May 5, 2026

@coderabbitai Fixed in 1ea81cc (nitpick from review body):

  • src/scanner/parser.rs: tightened unsupported_language_returns_error from is_err() to matches!(err, ZiftError::UnsupportedLanguage(Language::CSharp)) — pins the exact variant so a regression back to General would be caught.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 5, 2026

Tip

For best results, initiate chat on the files or code changes.

@jhawlwut: Great improvement — pinning the exact variant with matches!(err, ZiftError::UnsupportedLanguage(Language::CSharp)) is exactly the right move. A future regression back to ZiftError::General (or any other variant) will now be caught immediately rather than silently passing because the result was still an error. Thanks for tightening it up!

@jhawlwut jhawlwut self-assigned this May 5, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 5, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 5, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes May 5, 2026
jhawlwut added 6 commits May 5, 2026 09:20
Every internal module was pub, crystallising the entire codebase as a
semver commitment the moment the repo goes public.

Stable public surface (always pub):
  cli, error, types, rules, rego

Internal only (private mod — binary reaches them through lib::run):
  commands, logging

Internal, opt-in for integrators (pub only with --features unstable):
  config, deep, mcp, output, scanner

Adds a top-level `pub fn run(cli: Cli) -> Result<()>` so the binary
no longer needs to reach into private modules directly; main.rs is now
a four-line shim.

Pre-1.0 SemVer note: removing pub visibility from previously-public
modules is a breaking library API change → feat! to cut 0.2.0.
Two advertised-but-broken CLI surfaces that generate day-one bug
reports:

1. `--format sarif` parsed cleanly then returned a runtime error.
   Remove the OutputFormat::Sarif variant entirely; the match is now
   exhaustive over Text and Json. SARIF can land as a proper feat: in
   v0.2. AGENTS.md and docs/DESIGN.md updated to match.

2. get_language() returned ZiftError::General(String) for unsupported
   languages (CSharp, Kotlin, Ruby, Php). Replace with the new typed
   variant ZiftError::UnsupportedLanguage(Language) so callers can
   pattern-match on the specific case and the error message is
   consistent ("… is not yet supported in v0.1; support is planned for
   v0.2").
…bility

Privatising `mcp` and `deep` (per PUBLIC-1) made clippy stop assuming
external crates use these items, surfacing four pre-existing dead_code
warnings:

  - Candidate.kind / seed_category — read in tests + Debug, not in
    --lib clippy targets
  - error_code::INVALID_REQUEST — kept for JSON-RPC protocol completeness
  - FrameError::Parse { raw } — retained for Debug-trace diagnostics
  - HandlerError::Internal — matched in dispatch, reserved for future
    handler paths

#[allow(dead_code)] is the minimum-scope fix; deletion would broaden
the PR.
…tures

The four `tests/` integration tests reach into modules now gated behind
the `unstable` feature (deep, mcp, scanner, config). Adding
`required-features = ["unstable"]` so default `cargo test` skips them
cleanly, and updating CI to run `cargo test --all-features` and
`cargo clippy --all-features` so the full integration surface is still
exercised in CI.
@boorad boorad force-pushed the fix/oss-p0-surface branch from 4886b71 to 7b2f6ec Compare May 5, 2026 13:20
@boorad boorad merged commit c734608 into main May 5, 2026
2 of 3 checks passed
@boorad boorad deleted the fix/oss-p0-surface branch May 5, 2026 13:30
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