Skip to content

feat(reporter): add suppressible Pro conversion CTA to human-facing reports - #105

Open
affaan-m wants to merge 1 commit into
mainfrom
feat/pro-cta-footer
Open

feat(reporter): add suppressible Pro conversion CTA to human-facing reports#105
affaan-m wants to merge 1 commit into
mainfrom
feat/pro-cta-footer

Conversation

@affaan-m

@affaan-m affaan-m commented Jun 22, 2026

Copy link
Copy Markdown
Owner

Monetizes the free funnel (ecc-agentshield is doing ~30K downloads/month with near-zero bridge to paid). Adds a single, tasteful footer line to human-facing reports — no behavior change to detection, no noise in machine output.

What

  AgentShield - Security auditor for AI agent configs
  Scans run locally; nothing leaves your machine. Track fleet posture and drift over time with ECC Tools Pro: https://github.com/apps/ecc-tools
  • New src/reporter/cta.ts: shared CTA copy + opt-out logic.
  • Added to the terminal footer and the markdown report footer. The GitHub Action job summary reuses renderMarkdownReport, so it inherits the CTA automatically (third surface, zero extra code).
  • Not added to JSON or SARIF — those are machine-consumed and stay clean (asserted in tests).

Wedge

Leads with the privacy + low-noise differentiators (local-first, zero-account) and points at the real ECC Tools GitHub App. The free scanner stays the moat; the CTA only points at the hosted/fleet upgrade.

Opt-out

Suppress with ECC_NO_CTA=1 or AGENTSHIELD_NO_CTA=1 (empty / 0 / false do not suppress) — for clean CI logs and scripted use.

Verification

  • 9 new test assertions (tests/reporter/cta.test.ts + a markdown-vs-json integration check in json.test.ts).
  • Full suite green (1868 tests), tsc --noEmit + eslint clean.
  • CLI smoke: footer shows by default, ECC_NO_CTA=1 suppresses the CTA while keeping the existing footer.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added a Pro conversion call-to-action footer to human-facing report outputs (plain text and Markdown formats)
    • CTA can be suppressed via environment variables for users who prefer to opt out
  • Tests

    • Added comprehensive test coverage for CTA functionality, suppression behavior, and output formatting
    • Verified machine-readable outputs remain unaffected by CTA additions

Greptile Summary

Adds a suppressible Pro conversion CTA to the human-facing report surfaces (terminal footer and markdown/GitHub Action job summary) while keeping JSON and SARIF output machine-clean. The implementation is clean and well-scoped — new src/reporter/cta.ts centralises copy and opt-out logic, the two report renderers each call the appropriate helper, and the CTA unit tests use env injection for full determinism.

  • src/reporter/cta.ts introduces ctaSuppressed, proCtaPlainLines, and proCtaMarkdownLines with injectable env parameters, correct opt-out semantics (ECC_NO_CTA / AGENTSHIELD_NO_CTA), and separate plain-text and markdown variants.
  • renderMarkdownReport (which also backs the GitHub Action job summary) appends the markdown CTA; renderTerminalReport appends the plain-text CTA; renderJsonReport is untouched.
  • The integration test added to json.test.ts asserts CTA presence using real process.env, making it fragile if the documented opt-out env vars are set in the test environment.

Confidence Score: 4/5

Safe to merge with one test fix — no scanner logic, output formats, or security analysis paths are affected.

The integration test in json.test.ts asserts that "ECC Tools Pro" appears in the markdown output, but it calls renderMarkdownReport without injecting the env object, so it reads from real process.env. Any CI that has ECC_NO_CTA=1 set — following the PR's own opt-out guidance — will see this assertion fail. The rest of the change is clean: the source module, the two renderer edits, and the dedicated CTA unit tests are all correct.

tests/reporter/json.test.ts — the new integration test case needs env isolation (vi.stubEnv or explicit env deletion) to match the deterministic pattern used in cta.test.ts.

Important Files Changed

Filename Overview
src/reporter/cta.ts New module implementing CTA copy and opt-out logic. Well-structured with injectable env parameter for testability and correct suppression semantics (undefined, empty string, "0", and "false" are all treated as not-suppressed).
src/reporter/json.ts CTA footer appended to renderMarkdownReport only; renderJsonReport is untouched. The separator/body/link ordering in the markdown output is correct and the guard (cta.length > 0) is properly respected.
src/reporter/terminal.ts CTA inserted between the existing footer tagline and the trailing blank line. chalk.dim wrapping matches the surrounding footer style and the loop handles the empty-array (suppressed) case cleanly.
tests/reporter/cta.test.ts All four cases (default shown, both env var names, truthy values, and the three non-suppressing values) are covered. Env injection is used correctly throughout, making these tests fully deterministic.
tests/reporter/json.test.ts New CTA integration test relies on real process.env instead of injecting a controlled env, causing a fragile assertion that breaks when ECC_NO_CTA / AGENTSHIELD_NO_CTA is set in the test environment.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[SecurityReport] --> B[renderTerminalReport]
    A --> C[renderMarkdownReport]
    A --> D[renderJsonReport]
    A --> E[SARIF renderer]

    B --> F[proCtaPlainLines]
    C --> G[proCtaMarkdownLines]
    D --> H[No CTA — machine-clean]
    E --> I[No CTA — machine-clean]

    F --> J{ctaSuppressed?}
    G --> J

    J -- ECC_NO_CTA / AGENTSHIELD_NO_CTA set --> K[Returns empty array]
    J -- Not suppressed --> L[Returns CTA lines]

    K --> M[Footer unchanged]
    L --> N[CTA appended to footer]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[SecurityReport] --> B[renderTerminalReport]
    A --> C[renderMarkdownReport]
    A --> D[renderJsonReport]
    A --> E[SARIF renderer]

    B --> F[proCtaPlainLines]
    C --> G[proCtaMarkdownLines]
    D --> H[No CTA — machine-clean]
    E --> I[No CTA — machine-clean]

    F --> J{ctaSuppressed?}
    G --> J

    J -- ECC_NO_CTA / AGENTSHIELD_NO_CTA set --> K[Returns empty array]
    J -- Not suppressed --> L[Returns CTA lines]

    K --> M[Footer unchanged]
    L --> N[CTA appended to footer]
Loading

Reviews (1): Last reviewed commit: "feat(reporter): add suppressible Pro con..." | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

…eports

Monetize the free funnel (ecc-agentshield is ~30K downloads/month) with a single
tasteful footer line that leads with the privacy + low-noise wedge: 'Scans run
locally; nothing leaves your machine. Track fleet posture and drift over time
with ECC Tools Pro'. Points at the real GitHub App (github.com/apps/ecc-tools).

- New src/reporter/cta.ts: shared CTA copy + opt-out (ECC_NO_CTA /
  AGENTSHIELD_NO_CTA; empty/0/false do not suppress).
- Terminal footer + markdown report footer. The GitHub Action job summary reuses
  renderMarkdownReport, so it inherits the CTA automatically.
- Deliberately NOT added to JSON or SARIF (machine-consumed output stays clean).
- The free, local-first, zero-account scanner stays the moat; the CTA only points
  at the hosted/fleet upgrade.

9 new test assertions (cta.test.ts + a markdown-vs-json integration check). Full
suite green (1868), tsc + eslint clean, CLI smoke verified (footer shows by
default, ECC_NO_CTA=1 suppresses).
@ecc-tools

ecc-tools Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

ECC bundle files are already tracked in this repository. Skipping generation of another bundle PR.

@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown

Review Change Stack

Note

.coderabbit.yaml has unrecognized properties

CodeRabbit is using all valid settings from your configuration. Unrecognized properties (listed below) have been ignored and may indicate typos or deprecated fields that can be removed.

⚠️ Parsing warnings (1)
Validation error: Unrecognized key: "tools"
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: fecdd184-d80b-4b8d-b069-546795cab3aa

📥 Commits

Reviewing files that changed from the base of the PR and between 25d91f0 and 1fa90f1.

📒 Files selected for processing (5)
  • src/reporter/cta.ts
  • src/reporter/json.ts
  • src/reporter/terminal.ts
  • tests/reporter/cta.test.ts
  • tests/reporter/json.test.ts

📝 Walkthrough

Walkthrough

A new src/reporter/cta.ts module is added with Pro conversion CTA string constants, an env-var-based suppression check (ECC_NO_CTA / AGENTSHIELD_NO_CTA), and two line-generator helpers. The terminal reporter and markdown renderer each import the relevant helper and append the CTA footer when suppression is inactive. Tests cover content, default-enabled state, suppression, and falsy-value edge cases.

Changes

Pro CTA Footer

Layer / File(s) Summary
CTA module: constants, suppression, and line generators
src/reporter/cta.ts, tests/reporter/cta.test.ts
Exports PRO_CTA_PLAIN and PRO_CTA_MARKDOWN string templates, ctaSuppressed() that checks ECC_NO_CTA/AGENTSHIELD_NO_CTA env vars, and proCtaPlainLines/proCtaMarkdownLines that return footer lines or an empty array. Tests verify content, default-enabled behavior, suppression on truthy values, and non-suppression on falsy-like values ("", "0", "false").
Terminal and markdown reporter CTA integration
src/reporter/terminal.ts, src/reporter/json.ts, tests/reporter/json.test.ts
renderTerminalReport iterates proCtaPlainLines() and appends each line with chalk.dim before the final blank line. The markdown renderer in json.ts appends proCtaMarkdownLines() after the findings block. Tests assert "ECC Tools Pro" and the GitHub Apps URL appear in markdown output and are absent from renderJsonReport output.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main change: adding a suppressible Pro conversion CTA to human-facing reports, which is the core feature introduced across all modified files.
Docstring Coverage ✅ Passed Docstring coverage is 83.33% 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.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/pro-cta-footer

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Comment on lines +159 to +165
it("appends the Pro CTA footer (human-facing markdown only)", () => {
const output = renderMarkdownReport(makeReport());
expect(output).toContain("ECC Tools Pro");
expect(output).toContain("https://github.com/apps/ecc-tools");
// JSON output stays machine-clean: no marketing string.
expect(renderJsonReport(makeReport())).not.toContain("ECC Tools Pro");
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Integration test is environment-sensitive

renderMarkdownReport calls proCtaMarkdownLines() with no argument, so it reads from process.env directly. The assertion expect(output).toContain("ECC Tools Pro") will therefore fail whenever ECC_NO_CTA=1 or AGENTSHIELD_NO_CTA=1 is present in the test environment — which is exactly what the PR's own documented opt-out guidance tells CI users to set. A developer or CI pipeline that follows the suppression guidance and then runs npm test will see this test break.

The unit tests in cta.test.ts correctly inject a controlled env object, but this integration test bypasses that isolation. The fix is to either use vi.stubEnv / vi.unstubAllEnvs around this test, or delete the two env vars from process.env for the duration of the test.

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.

1 participant