Skip to content

recover the source from the published sourcemaps — 8 of 8 versions rebuild byte-identically - #18

Open
yakimoto wants to merge 1 commit into
mainfrom
recover/source-from-published-sourcemaps
Open

recover the source from the published sourcemaps — 8 of 8 versions rebuild byte-identically#18
yakimoto wants to merge 1 commit into
mainfrom
recover/source-from-published-sourcemaps

Conversation

@yakimoto

@yakimoto yakimoto commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

This repo advertises itself as the source of @wave-av/cli and contains none of it. Eight versions were published between 2026-04-03 and 2026-08-04 from a working copy that was never committed — so a stranger who runs npm install @wave-av/cli and follows the repository link the package itself carries arrives at a README and a LICENSE, while the code executing on their machine exists in no public repository.

The source was never lost — it ships in every tarball

Every published version carries dist/index.js.map, and that sourcemap carries sourcesContent: not the names of the original files but their complete contents, pre-compilation. All 70 TypeScript files in this PR were extracted from it verbatim. Nothing was inferred from the compiled bundle, hand-written to match, or reasoned backwards from the type declarations.

The receipt — every version, not a sample

version rebuilt dist/index.js vs published
1.0.0 · 1.0.2 · 1.0.3 · 1.0.4 byte-identical
1.0.5 · 1.0.6 · 1.0.7 · 1.0.8 byte-identical

cmp exits 0 silently on all eight. RECOVERY.md carries the three commands to re-derive any row from scratch.

This is a reproducible-build proof, which is a stronger claim than the recovery bar asked for — that bar was a matching file list; this is the matching bundle, byte for byte.

What was AUTHORED, and is therefore not recovered

Two files, called out here rather than left looking like they came out of the artifact, because a sourcemap contains source and not build configuration:

  • tsconfig.json — conventional strict ES2022/ESNext
  • tsup.config.ts — entry src/index.ts, ESM, node18, sourcemap, shebang banner

They are not loose guesses: they are the settings under which output matches the published bytes exactly, eight times over. A different plausible configuration would have produced a different bundle and every comparison above would have failed. But written is not recovered, and conflating those two is the exact class of error this exercise exists to correct.

package.json is the published manifest, which npm preserves in full including scripts and devDependencies.

Safety

gitleaks with this repo's own .gitleaks.toml: no leaks found, 251 KB scanned. Worth stating why that check came first — the sourcemap has been publicly downloadable since April, so a credential inside it would have been a live four-month exposure, a fact about the published package rather than a risk created by recovering it. It is clean.

What this unblocks, and what it deliberately does not

Unblocks #17. That publish workflow is correct and cannot run: its verify job dies at npm ci against a repo with no package.json. The workflow was never the blocker; the missing source was. Do not weaken #17 to make it green — merge this first.

Does not create the tags. Recovering source does not retroactively produce the tags these eight versions never had. Tagging each against its own cmp receipt is tracked separately, and tags on a public repo are a claim that this commit produced that artifact — checkable, permanent, and worse than no tag if wrong.

Says nothing about @wave-av/workflow-sdk. Its seven versions carry no sourcemap at all. That source is recoverable only as a reconstruction — a tree provably producing the published bytes, which is genuinely weaker than a tree that did produce them. Both end with a repo that builds and publishes identical output; only one is true, and they must not be recorded as the same thing.

Refs wave-av/claude-workstation#1624


Note

Cursor Bugbot is generating a summary for commit 8ce183a. Configure here.

Review in cubic

Note

Add Wave CLI source recovered from published sourcemaps with full command set

  • Recovers the full TypeScript source of the Wave CLI from published npm sourcemaps, rebuilding byte-identically across all 8 versions, as documented in RECOVERY.md.
  • Establishes the CLI entrypoint, Commander program wiring, config schema, keychain-based credential storage, and device-flow OAuth login in src/.
  • Adds ~40 command namespaces covering streams, studio, auth, billing, logs, analytics, DRM, Zoom, signage, and more, each delegating to a typed @wave/sdk client.
  • Adds project scaffolding templates (blank, podcast, multi-camera, SRT, WebRTC, webhook handler, API integration, studio plugin) with package.json and .env.example files.
  • Adds shared output utilities (table, JSON, YAML, spinner, confirm prompts) and an SSE client for real-time log/event tailing.

Macroscope summarized 8ce183a.

…build byte-identically

This repo advertised itself as the source of @wave-av/cli while containing none
of it. Eight versions were published between 2026-04-03 and 2026-08-04 from a
working copy never committed, so anyone who followed the repository link the
package itself carries arrived at a README and a LICENSE while the code running
on their machine existed in no public repository.

The source was not lost. Every published version ships dist/index.js.map, and
that sourcemap carries sourcesContent — not the names of the original files but
their complete contents. All 70 TypeScript files here were extracted from it
verbatim; nothing was inferred from the bundle or hand-written to match.

The claim is checkable, so it was checked on every version rather than a sample:
1.0.0, 1.0.2, 1.0.3, 1.0.4, 1.0.5, 1.0.6, 1.0.7 and 1.0.8 each rebuild to a
dist/index.js that is BYTE-IDENTICAL to the artifact npm shipped. RECOVERY.md
carries the three commands to re-derive any row.

Two files were AUTHORED for this recovery and are labelled as such rather than
left to look like they came out of the artifact: tsconfig.json and
tsup.config.ts. A sourcemap contains source, not build configuration. They are
not loose guesses — they are the settings under which the output matches the
published bytes exactly, eight times over — but written is not recovered, and
conflating the two would be the error this exercise exists to correct.
package.json is the published manifest, which npm preserves in full.

gitleaks: no leaks found, 251 KB scanned with this repo own .gitleaks.toml. That
mattered: the sourcemap has been publicly downloadable since April, so a
credential in it would have been a live four-month exposure rather than a risk
created by recovering it.

This unblocks the publish workflow in #17, whose verify job cannot run npm ci
against a repo with no package.json. It does NOT create the tags the eight
published versions never had; tagging each against its own cmp receipt is
tracked separately.

Refs wave-av/claude-workstation#1624
@cursor

cursor Bot commented Aug 5, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_a509e33a-04e3-4635-a08f-28a23f8cc7ed)

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 35 minutes

Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab.

How can I continue?

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.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f8b58218-b5e4-40f8-ad31-60e7a8404396

📥 Commits

Reviewing files that changed from the base of the PR and between 80d078b and 8ce183a.

📒 Files selected for processing (99)
  • .gitignore
  • RECOVERY.md
  • package.json
  • src/cli.ts
  • src/commands/admin/index.ts
  • src/commands/ai/index.ts
  • src/commands/analytics/index.ts
  • src/commands/api/index.ts
  • src/commands/audience/index.ts
  • src/commands/auth/index.ts
  • src/commands/billing/index.ts
  • src/commands/captions/index.ts
  • src/commands/chapters/index.ts
  • src/commands/clips/index.ts
  • src/commands/collab/index.ts
  • src/commands/completion/index.ts
  • src/commands/config/index.ts
  • src/commands/connect/index.ts
  • src/commands/creator/index.ts
  • src/commands/desktop/index.ts
  • src/commands/dev/index.ts
  • src/commands/distribution/index.ts
  • src/commands/doctor/index.ts
  • src/commands/drm/index.ts
  • src/commands/edge/index.ts
  • src/commands/editor/index.ts
  • src/commands/fleet/index.ts
  • src/commands/ghost/index.ts
  • src/commands/init/index.ts
  • src/commands/link/index.ts
  • src/commands/listen/index.ts
  • src/commands/logs/index.ts
  • src/commands/marketplace/index.ts
  • src/commands/mesh/index.ts
  • src/commands/notify/index.ts
  • src/commands/open/index.ts
  • src/commands/org/index.ts
  • src/commands/phone/index.ts
  • src/commands/podcast/index.ts
  • src/commands/prism/index.ts
  • src/commands/qr/index.ts
  • src/commands/scene/index.ts
  • src/commands/search/index.ts
  • src/commands/sentiment/index.ts
  • src/commands/signage/index.ts
  • src/commands/slides/index.ts
  • src/commands/status/index.ts
  • src/commands/stream/index.ts
  • src/commands/studio/index.ts
  • src/commands/transcribe/index.ts
  • src/commands/trigger/index.ts
  • src/commands/usb/index.ts
  • src/commands/vault/index.ts
  • src/commands/voice/index.ts
  • src/commands/zoom/index.ts
  • src/index.ts
  • src/lib/api-client.ts
  • src/lib/auth/device-flow.ts
  • src/lib/auth/keychain.ts
  • src/lib/config/manager.ts
  • src/lib/config/schema.ts
  • src/lib/environment.ts
  • src/lib/errors.ts
  • src/lib/exit-codes.ts
  • src/lib/output/confirm.ts
  • src/lib/output/index.ts
  • src/lib/output/json.ts
  • src/lib/output/spinner.ts
  • src/lib/output/table.ts
  • src/lib/output/yaml.ts
  • src/lib/prompts.ts
  • src/lib/sse-client.ts
  • src/lib/suggestions.ts
  • templates/api-integration/.env.example
  • templates/api-integration/package.json
  • templates/api-integration/src/index.ts
  • templates/blank/.env.example
  • templates/blank/package.json
  • templates/blank/src/index.ts
  • templates/multi-camera/.env.example
  • templates/multi-camera/package.json
  • templates/multi-camera/src/index.ts
  • templates/podcast/.env.example
  • templates/podcast/package.json
  • templates/podcast/src/index.ts
  • templates/srt-contribution/.env.example
  • templates/srt-contribution/package.json
  • templates/srt-contribution/src/index.ts
  • templates/studio-plugin/.env.example
  • templates/studio-plugin/package.json
  • templates/studio-plugin/src/index.ts
  • templates/webhook-handler/.env.example
  • templates/webhook-handler/package.json
  • templates/webhook-handler/src/index.ts
  • templates/webrtc-demo/.env.example
  • templates/webrtc-demo/package.json
  • templates/webrtc-demo/src/index.ts
  • tsconfig.json
  • tsup.config.ts

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

@macroscopeapp

macroscopeapp Bot commented Aug 5, 2026

Copy link
Copy Markdown

Approvability

Verdict: Needs human review

Unable to check for correctness in 8ce183a. Diff is too large for automated approval analysis. A human reviewer should evaluate this PR.

You can customize Macroscope's approvability policy. Learn more.

console.log(`Recording ready: ${event.data.recording_url}`);
break;
default:
console.log(`Unhandled event type: ${event.type}`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Semgrep identified a blocking 🔴 issue in your code:
Detected a logger that logs user input without properly neutralizing the output. The log message could contain characters like and and cause an attacker to forge log entries or include malicious content into the logs. Use proper input validation and/or output encoding to prevent log entries from being forged.

Dataflow graph
flowchart LR
    classDef invis fill:white, stroke: none
    classDef default fill:#e7f5ff, color:#1c7fd6, stroke: none

    subgraph File0["<b>templates/webhook-handler/src/index.ts</b>"]
        direction LR
        %% Source

        subgraph Source
            direction LR

            v0["<a href=https://github.com/wave-av/cli/blob/8ce183a2aeac624cb9bbb9122b90ddfbfcef458f/templates/webhook-handler/src/index.ts#L29 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 29] req</a>"]
        end
        %% Intermediate

        subgraph Traces0[Traces]
            direction TB

            v2["<a href=https://github.com/wave-av/cli/blob/8ce183a2aeac624cb9bbb9122b90ddfbfcef458f/templates/webhook-handler/src/index.ts#L29 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 29] event</a>"]

            v3["<a href=https://github.com/wave-av/cli/blob/8ce183a2aeac624cb9bbb9122b90ddfbfcef458f/templates/webhook-handler/src/index.ts#L43 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 43] `</a>"]
        end
            v2 --> v3
        %% Sink

        subgraph Sink
            direction LR

            v1["<a href=https://github.com/wave-av/cli/blob/8ce183a2aeac624cb9bbb9122b90ddfbfcef458f/templates/webhook-handler/src/index.ts#L43 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 43] console.log(`Unhandled event type: ${event.type}`)</a>"]
        end
    end
    %% Class Assignment
    Source:::invis
    Sink:::invis

    Traces0:::invis
    File0:::invis

    %% Connections

    Source --> Traces0
    Traces0 --> Sink


Loading

To resolve this comment:

🔧 No guidance has been designated for this issue. Fix according to your organization's approved methods.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by console-log-express.

You can view more details about this finding in the Semgrep AppSec Platform.

console.log(`Stream ${event.data.stream_id} ended`);
break;
case "recording.ready":
console.log(`Recording ready: ${event.data.recording_url}`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Semgrep identified a blocking 🔴 issue in your code:
Detected a logger that logs user input without properly neutralizing the output. The log message could contain characters like and and cause an attacker to forge log entries or include malicious content into the logs. Use proper input validation and/or output encoding to prevent log entries from being forged.

Dataflow graph
flowchart LR
    classDef invis fill:white, stroke: none
    classDef default fill:#e7f5ff, color:#1c7fd6, stroke: none

    subgraph File0["<b>templates/webhook-handler/src/index.ts</b>"]
        direction LR
        %% Source

        subgraph Source
            direction LR

            v0["<a href=https://github.com/wave-av/cli/blob/8ce183a2aeac624cb9bbb9122b90ddfbfcef458f/templates/webhook-handler/src/index.ts#L29 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 29] req</a>"]
        end
        %% Intermediate

        subgraph Traces0[Traces]
            direction TB

            v2["<a href=https://github.com/wave-av/cli/blob/8ce183a2aeac624cb9bbb9122b90ddfbfcef458f/templates/webhook-handler/src/index.ts#L29 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 29] event</a>"]

            v3["<a href=https://github.com/wave-av/cli/blob/8ce183a2aeac624cb9bbb9122b90ddfbfcef458f/templates/webhook-handler/src/index.ts#L40 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 40] `</a>"]
        end
            v2 --> v3
        %% Sink

        subgraph Sink
            direction LR

            v1["<a href=https://github.com/wave-av/cli/blob/8ce183a2aeac624cb9bbb9122b90ddfbfcef458f/templates/webhook-handler/src/index.ts#L40 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 40] console.log(`Recording ready: ${event.data.recording_url}`)</a>"]
        end
    end
    %% Class Assignment
    Source:::invis
    Sink:::invis

    Traces0:::invis
    File0:::invis

    %% Connections

    Source --> Traces0
    Traces0 --> Sink


Loading

To resolve this comment:

🔧 No guidance has been designated for this issue. Fix according to your organization's approved methods.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by console-log-express.

You can view more details about this finding in the Semgrep AppSec Platform.

console.log(`Stream ${event.data.stream_id} started`);
break;
case "stream.ended":
console.log(`Stream ${event.data.stream_id} ended`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Semgrep identified a blocking 🔴 issue in your code:
Detected a logger that logs user input without properly neutralizing the output. The log message could contain characters like and and cause an attacker to forge log entries or include malicious content into the logs. Use proper input validation and/or output encoding to prevent log entries from being forged.

Dataflow graph
flowchart LR
    classDef invis fill:white, stroke: none
    classDef default fill:#e7f5ff, color:#1c7fd6, stroke: none

    subgraph File0["<b>templates/webhook-handler/src/index.ts</b>"]
        direction LR
        %% Source

        subgraph Source
            direction LR

            v0["<a href=https://github.com/wave-av/cli/blob/8ce183a2aeac624cb9bbb9122b90ddfbfcef458f/templates/webhook-handler/src/index.ts#L29 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 29] req</a>"]
        end
        %% Intermediate

        subgraph Traces0[Traces]
            direction TB

            v2["<a href=https://github.com/wave-av/cli/blob/8ce183a2aeac624cb9bbb9122b90ddfbfcef458f/templates/webhook-handler/src/index.ts#L29 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 29] event</a>"]

            v3["<a href=https://github.com/wave-av/cli/blob/8ce183a2aeac624cb9bbb9122b90ddfbfcef458f/templates/webhook-handler/src/index.ts#L37 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 37] `</a>"]
        end
            v2 --> v3
        %% Sink

        subgraph Sink
            direction LR

            v1["<a href=https://github.com/wave-av/cli/blob/8ce183a2aeac624cb9bbb9122b90ddfbfcef458f/templates/webhook-handler/src/index.ts#L37 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 37] console.log(`Stream ${event.data.stream_id} ended`)</a>"]
        end
    end
    %% Class Assignment
    Source:::invis
    Sink:::invis

    Traces0:::invis
    File0:::invis

    %% Connections

    Source --> Traces0
    Traces0 --> Sink


Loading

To resolve this comment:

🔧 No guidance has been designated for this issue. Fix according to your organization's approved methods.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by console-log-express.

You can view more details about this finding in the Semgrep AppSec Platform.


switch (event.type) {
case "stream.started":
console.log(`Stream ${event.data.stream_id} started`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Semgrep identified a blocking 🔴 issue in your code:
Detected a logger that logs user input without properly neutralizing the output. The log message could contain characters like and and cause an attacker to forge log entries or include malicious content into the logs. Use proper input validation and/or output encoding to prevent log entries from being forged.

Dataflow graph
flowchart LR
    classDef invis fill:white, stroke: none
    classDef default fill:#e7f5ff, color:#1c7fd6, stroke: none

    subgraph File0["<b>templates/webhook-handler/src/index.ts</b>"]
        direction LR
        %% Source

        subgraph Source
            direction LR

            v0["<a href=https://github.com/wave-av/cli/blob/8ce183a2aeac624cb9bbb9122b90ddfbfcef458f/templates/webhook-handler/src/index.ts#L29 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 29] req</a>"]
        end
        %% Intermediate

        subgraph Traces0[Traces]
            direction TB

            v2["<a href=https://github.com/wave-av/cli/blob/8ce183a2aeac624cb9bbb9122b90ddfbfcef458f/templates/webhook-handler/src/index.ts#L29 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 29] event</a>"]

            v3["<a href=https://github.com/wave-av/cli/blob/8ce183a2aeac624cb9bbb9122b90ddfbfcef458f/templates/webhook-handler/src/index.ts#L34 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 34] `</a>"]
        end
            v2 --> v3
        %% Sink

        subgraph Sink
            direction LR

            v1["<a href=https://github.com/wave-av/cli/blob/8ce183a2aeac624cb9bbb9122b90ddfbfcef458f/templates/webhook-handler/src/index.ts#L34 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 34] console.log(`Stream ${event.data.stream_id} started`)</a>"]
        end
    end
    %% Class Assignment
    Source:::invis
    Sink:::invis

    Traces0:::invis
    File0:::invis

    %% Connections

    Source --> Traces0
    Traces0 --> Sink


Loading

To resolve this comment:

🔧 No guidance has been designated for this issue. Fix according to your organization's approved methods.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by console-log-express.

You can view more details about this finding in the Semgrep AppSec Platform.

}

const event = req.body;
console.log(`Received event: ${event.type}`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Semgrep identified a blocking 🔴 issue in your code:
Detected a logger that logs user input without properly neutralizing the output. The log message could contain characters like and and cause an attacker to forge log entries or include malicious content into the logs. Use proper input validation and/or output encoding to prevent log entries from being forged.

Dataflow graph
flowchart LR
    classDef invis fill:white, stroke: none
    classDef default fill:#e7f5ff, color:#1c7fd6, stroke: none

    subgraph File0["<b>templates/webhook-handler/src/index.ts</b>"]
        direction LR
        %% Source

        subgraph Source
            direction LR

            v0["<a href=https://github.com/wave-av/cli/blob/8ce183a2aeac624cb9bbb9122b90ddfbfcef458f/templates/webhook-handler/src/index.ts#L29 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 29] req</a>"]
        end
        %% Intermediate

        subgraph Traces0[Traces]
            direction TB

            v2["<a href=https://github.com/wave-av/cli/blob/8ce183a2aeac624cb9bbb9122b90ddfbfcef458f/templates/webhook-handler/src/index.ts#L29 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 29] event</a>"]

            v3["<a href=https://github.com/wave-av/cli/blob/8ce183a2aeac624cb9bbb9122b90ddfbfcef458f/templates/webhook-handler/src/index.ts#L30 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 30] `</a>"]
        end
            v2 --> v3
        %% Sink

        subgraph Sink
            direction LR

            v1["<a href=https://github.com/wave-av/cli/blob/8ce183a2aeac624cb9bbb9122b90ddfbfcef458f/templates/webhook-handler/src/index.ts#L30 target=_blank style='text-decoration:none; color:#1c7fd6'>[Line: 30] console.log(`Received event: ${event.type}`)</a>"]
        end
    end
    %% Class Assignment
    Source:::invis
    Sink:::invis

    Traces0:::invis
    File0:::invis

    %% Connections

    Source --> Traces0
    Traces0 --> Sink


Loading

To resolve this comment:

🔧 No guidance has been designated for this issue. Fix according to your organization's approved methods.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by console-log-express.

You can view more details about this finding in the Semgrep AppSec Platform.

if (typeof current[key] !== "object" || current[key] === null) {
current[key] = {};
}
current = current[key] as Record<string, unknown>;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Semgrep identified an issue in your code:
Possibility of prototype polluting function detected. By adding or modifying attributes of an object prototype, it is possible to create attributes that exist on every object, or replace critical attributes with malicious ones. This can be problematic if the software depends on existence or non-existence of certain attributes, or uses pre-defined attributes of object prototype (such as hasOwnProperty, toString or valueOf). Possible mitigations might be: freezing the object prototype, using an object without prototypes (via Object.create(null) ), blocking modifications of attributes that resolve to object prototype, using Map instead of object.

To resolve this comment:

🔧 No guidance has been designated for this issue. Fix according to your organization's approved methods.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by prototype-pollution-loop.

You can view more details about this finding in the Semgrep AppSec Platform.

if (current === null || current === undefined || typeof current !== "object") {
return undefined;
}
current = (current as Record<string, unknown>)[key];

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Semgrep identified an issue in your code:
Possibility of prototype polluting function detected. By adding or modifying attributes of an object prototype, it is possible to create attributes that exist on every object, or replace critical attributes with malicious ones. This can be problematic if the software depends on existence or non-existence of certain attributes, or uses pre-defined attributes of object prototype (such as hasOwnProperty, toString or valueOf). Possible mitigations might be: freezing the object prototype, using an object without prototypes (via Object.create(null) ), blocking modifications of attributes that resolve to object prototype, using Map instead of object.

To resolve this comment:

🔧 No guidance has been designated for this issue. Fix according to your organization's approved methods.

💬 Ignore this finding

Reply with Semgrep commands to ignore this finding.

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by prototype-pollution-loop.

You can view more details about this finding in the Semgrep AppSec Platform.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Recover @wave-av/cli source from published sourcemaps (1.0.0–1.0.8 reproducible)

✨ Enhancement 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Add recovered TypeScript source for @wave-av/cli extracted verbatim from published sourcemaps.
• Document byte-identical rebuild verification across npm releases 1.0.0 through 1.0.8.
• Add build/config files and templates needed to reproduce the published dist bundle.
Diagram

graph TD
  A["src/index.ts"] --> B["src/cli.ts"] --> C["Command groups"] --> D["lib/* helpers"] --> E{{"WAVE API (via @wave-av/sdk)"}}
  D --> F[("~/.wave storage")]
  C --> G["templates/*"]
  subgraph Legend
    direction LR
    _m["Module"] ~~~ _fs[("Filesystem")] ~~~ _ext{{"External"}}
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Re-publish with new source-of-truth repo + deprecate old versions
  • ➕ Clean provenance story (new tags, commits, provenance on publish).
  • ➕ Avoids mixing recovered code with newly-authored build config in one step.
  • ➖ Doesn’t fix the historical gap for already-installed 1.0.x users.
  • ➖ More operational overhead (deprecations, comms, potential breaking metadata changes).
2. Attach source artifacts per version (git tags or release assets)
  • ➕ Makes each published version independently auditable.
  • ➕ Keeps the recovery record per-version without forcing a single ‘current’ tree.
  • ➖ More bookkeeping (8 tags/releases) and ongoing maintenance burden.
  • ➖ Still needs a build config baseline to reproduce dist consistently.
3. Keep repo dist-only and document it explicitly
  • ➕ Minimal code review surface; avoids reintroducing large codebase.
  • ➕ Lower risk of accidental behavior changes if source diverges.
  • ➖ Does not restore auditability or contributor workflow.
  • ➖ Continues to block CI, tests, and future maintenance improvements.

Recommendation: The PR’s approach (verbatim extraction from sourcesContent plus a reproducible-build receipt) is the strongest way to re-establish auditability for the already-published 1.0.x artifacts. If desired, follow up by adding signed tags/releases per version and enabling npm provenance going forward, but keep this recovery as the canonical historical source for 1.0.0–1.0.8.

Files changed (99) +6617 / -0

Enhancement (94) +6409 / -0
index.tsAdd CLI entrypoint that parses argv +11/-0

Add CLI entrypoint that parses argv

• Introduces the executable entrypoint that creates the program and runs commander parsing with basic error handling.

src/index.ts

cli.tsCreate Commander program and register all command groups +174/-0

Create Commander program and register all command groups

• Defines global CLI options, prints an ASCII banner for interactive use, and registers all domain command groups under src/commands/*.

src/cli.ts

index.tsAdd admin command group +75/-0

Add admin command group

• Registers the admin command namespace and its subcommands/actions using shared error handling and output formatting.

src/commands/admin/index.ts

index.tsAdd AI command group +54/-0

Add AI command group

• Registers AI-related CLI commands and wires them to API calls via the shared client helper.

src/commands/ai/index.ts

index.tsAdd analytics command group +54/-0

Add analytics command group

• Registers analytics commands and formats responses for table/json/yaml output.

src/commands/analytics/index.ts

index.tsAdd API command group utilities +82/-0

Add API command group utilities

• Registers API-focused commands intended to assist with API usage and troubleshooting from the CLI.

src/commands/api/index.ts

index.tsAdd audience command group +136/-0

Add audience command group

• Registers audience-related commands and parameters, using shared confirmation/output helpers where needed.

src/commands/audience/index.ts

index.tsAdd auth/login/logout/status and whoami +139/-0

Add auth/login/logout/status and whoami

• Implements authentication commands including RFC8628 device flow login, API key storage, logout, status, and a top-level whoami alias.

src/commands/auth/index.ts

index.tsAdd billing command group +110/-0

Add billing command group

• Registers billing-related commands (limits/upgrade/etc.) and integrates with error suggestions for rate limiting.

src/commands/billing/index.ts

index.tsAdd captions command group +60/-0

Add captions command group

• Registers captions-related commands and formats results via the common output layer.

src/commands/captions/index.ts

index.tsAdd chapters command group +57/-0

Add chapters command group

• Registers chapter management commands and uses the shared API client for requests.

src/commands/chapters/index.ts

index.tsAdd clips command group +78/-0

Add clips command group

• Registers clip management commands and binds them to Wave SDK calls with standardized output.

src/commands/clips/index.ts

index.tsAdd collaboration command group +71/-0

Add collaboration command group

• Adds collab-oriented commands under a dedicated namespace with common error wrapping.

src/commands/collab/index.ts

index.tsAdd shell completion script generator +140/-0

Add shell completion script generator

• Adds bash/zsh/fish completion generation based on the Commander command registry.

src/commands/completion/index.ts

index.tsAdd config command group +94/-0

Add config command group

• Registers config inspection/update commands backed by the local config manager and schema validation.

src/commands/config/index.ts

index.tsAdd connect command group +66/-0

Add connect command group

• Registers connect/integration commands and routes operations through the shared API client.

src/commands/connect/index.ts

index.tsAdd creator command group +64/-0

Add creator command group

• Introduces creator-related command namespace and output formatting for API responses.

src/commands/creator/index.ts

index.tsAdd desktop command group +44/-0

Add desktop command group

• Registers desktop-related commands and standardizes error handling and formatting.

src/commands/desktop/index.ts

index.tsAdd developer tooling command group +256/-0

Add developer tooling command group

• Adds developer-oriented commands for debugging/automation and integrates shared prompts/output helpers.

src/commands/dev/index.ts

index.tsAdd distribution command group +74/-0

Add distribution command group

• Registers distribution/publishing oriented commands and connects them to the Wave API via SDK.

src/commands/distribution/index.ts

index.tsAdd doctor diagnostics command group +143/-0

Add doctor diagnostics command group

• Adds diagnostic commands to inspect environment/config/auth and report actionable results.

src/commands/doctor/index.ts

index.tsAdd DRM command group +146/-0

Add DRM command group

• Registers DRM-related operations with consistent confirmation and output handling.

src/commands/drm/index.ts

index.tsAdd edge command group +82/-0

Add edge command group

• Registers edge-related commands for infrastructure operations and formats results consistently.

src/commands/edge/index.ts

index.tsAdd editor command group +58/-0

Add editor command group

• Registers editor-related commands and binds them to Wave SDK calls.

src/commands/editor/index.ts

index.tsAdd fleet command group +66/-0

Add fleet command group

• Adds fleet management commands and uses shared client/auth/config helpers.

src/commands/fleet/index.ts

index.tsAdd ghost command group +51/-0

Add ghost command group

• Registers ghost-related commands and integrates the standard output layer.

src/commands/ghost/index.ts

index.tsAdd project scaffolding via templates +253/-0

Add project scaffolding via templates

• Implements 'wave init' to select a template, copy template files, rewrite package name, generate starter config/README, and optionally install dependencies.

src/commands/init/index.ts

index.tsAdd link command group +218/-0

Add link command group

• Registers link-related commands for associating resources and printing formatted results.

src/commands/link/index.ts

index.tsAdd listen command group +66/-0

Add listen command group

• Adds commands that listen/stream events and integrate with SSE support and output formatting.

src/commands/listen/index.ts

index.tsAdd logs command group +90/-0

Add logs command group

• Registers log retrieval/streaming commands and formats output for terminal and agents.

src/commands/logs/index.ts

index.tsAdd marketplace command group +65/-0

Add marketplace command group

• Introduces marketplace-related commands and routes them through the shared API client.

src/commands/marketplace/index.ts

index.tsAdd mesh command group +55/-0

Add mesh command group

• Registers mesh/infrastructure commands and applies the standard error wrapping.

src/commands/mesh/index.ts

index.tsAdd notify command group +88/-0

Add notify command group

• Adds notification-related commands with consistent formatting and error handling.

src/commands/notify/index.ts

index.tsAdd open command group +51/-0

Add open command group

• Registers commands for opening relevant web resources/URLs from the CLI.

src/commands/open/index.ts

index.tsAdd organization command group +73/-0

Add organization command group

• Adds organization context commands and integrates config selection and output formatting.

src/commands/org/index.ts

index.tsAdd phone command group +86/-0

Add phone command group

• Registers phone-related production commands and routes calls via the Wave SDK client.

src/commands/phone/index.ts

index.tsAdd podcast command group +123/-0

Add podcast command group

• Adds podcast workflow commands and formats responses for multiple output modes.

src/commands/podcast/index.ts

index.tsAdd prism command group +64/-0

Add prism command group

• Registers prism-related commands and uses shared helpers for API access and output.

src/commands/prism/index.ts

index.tsAdd QR command group +51/-0

Add QR command group

• Registers QR-related commands and integrates the standard output layer.

src/commands/qr/index.ts

index.tsAdd scene command group +51/-0

Add scene command group

• Registers scene-related commands and wires them to API calls with error wrapping.

src/commands/scene/index.ts

index.tsAdd search command group +74/-0

Add search command group

• Registers search commands and formats search results via the common output helpers.

src/commands/search/index.ts

index.tsAdd sentiment command group +47/-0

Add sentiment command group

• Registers sentiment-related commands and uses shared client/output utilities.

src/commands/sentiment/index.ts

index.tsAdd signage command group +126/-0

Add signage command group

• Registers signage commands and uses confirmation/output helpers for destructive operations.

src/commands/signage/index.ts

index.tsAdd slides command group +60/-0

Add slides command group

• Registers slide-related commands and formats output consistently across modes.

src/commands/slides/index.ts

index.tsAdd status command group +68/-0

Add status command group

• Adds CLI commands to query and display system/resource status.

src/commands/status/index.ts

index.tsAdd stream lifecycle commands (create/list/get/update/delete/start/stop) +167/-0

Add stream lifecycle commands (create/list/get/update/delete/start/stop)

• Implements core stream management commands backed by the Wave SDK, including destructive confirmations and formatted output.

src/commands/stream/index.ts

index.tsAdd studio command group +143/-0

Add studio command group

• Registers studio/production-related commands and routes them via the shared API client.

src/commands/studio/index.ts

index.tsAdd transcribe command group +52/-0

Add transcribe command group

• Registers transcription-related commands and integrates standard output formatting.

src/commands/transcribe/index.ts

index.tsAdd trigger command group +71/-0

Add trigger command group

• Registers trigger/automation commands with shared error handling and output formatting.

src/commands/trigger/index.ts

index.tsAdd USB command group +61/-0

Add USB command group

• Registers USB/hardware-related commands and formats API responses consistently.

src/commands/usb/index.ts

index.tsAdd vault command group +81/-0

Add vault command group

• Registers vault/content storage commands and uses shared client/output helpers.

src/commands/vault/index.ts

index.tsAdd voice command group +56/-0

Add voice command group

• Registers voice-related commands and integrates standard output handling.

src/commands/voice/index.ts

index.tsAdd zoom command group +131/-0

Add zoom command group

• Registers Zoom integration commands and routes operations through the shared API client.

src/commands/zoom/index.ts

api-client.tsCentralize Wave SDK client creation and env/config overrides +63/-0

Centralize Wave SDK client creation and env/config overrides

• Creates an authenticated Wave SDK client using env vars or local config + keychain, and wires SDK retry/rate-limit events to CLI warnings.

src/lib/api-client.ts

device-flow.tsImplement RFC8628 device authorization flow for login +154/-0

Implement RFC8628 device authorization flow for login

• Adds device authorization start + polling logic, including browser open behavior and RFC-defined error handling for slow_down/pending/expired.

src/lib/auth/device-flow.ts

keychain.tsPersist API keys via keytar with secure file fallback +111/-0

Persist API keys via keytar with secure file fallback

• Stores/retrieves/deletes API keys using keytar when available, otherwise falls back to a chmod 0600 JSON file in ~/.wave.

src/lib/auth/keychain.ts

manager.tsAdd local config load/save/update with schema validation +54/-0

Add local config load/save/update with schema validation

• Implements ~/.wave config file management with safe defaults, zod validation, and atomic writes via a temporary file.

src/lib/config/manager.ts

schema.tsDefine config schema and defaults +33/-0

Define config schema and defaults

• Adds the configuration schema and default config generator used by the config manager to validate and initialize user settings.

src/lib/config/schema.ts

environment.tsDetect CI/agent/interactive environment and default output format +66/-0

Detect CI/agent/interactive environment and default output format

• Adds environment detection (CI vs AI agent vs interactive) and derives default output formatting preferences including color support.

src/lib/environment.ts

errors.tsStandardize CLI error formatting, suggestions, and exit codes +108/-0

Standardize CLI error formatting, suggestions, and exit codes

• Adds centralized error handling that maps SDK errors to exit codes and prints either human-friendly suggestions or structured JSON for agents.

src/lib/errors.ts

exit-codes.tsDefine CLI exit code constants +20/-0

Define CLI exit code constants

• Introduces consistent exit codes for common failure modes (auth required, rate limited, validation, etc.).

src/lib/exit-codes.ts

confirm.tsAdd destructive action confirmation helper +20/-0

Add destructive action confirmation helper

• Implements confirmation prompts for destructive operations, with support for non-interactive/auto-confirm flows.

src/lib/output/confirm.ts

index.tsAdd unified output formatting facade +33/-0

Add unified output formatting facade

• Provides a single formatOutput entrypoint and re-exports table/json/yaml/spinner/confirm helpers for command modules.

src/lib/output/index.ts

json.tsAdd JSON output formatter +8/-0

Add JSON output formatter

• Implements a JSON formatter used when output mode is json or when running non-interactively.

src/lib/output/json.ts

spinner.tsAdd spinner utilities for long-running tasks +18/-0

Add spinner utilities for long-running tasks

• Adds spinner helpers used by commands like init to provide progress feedback in interactive terminals.

src/lib/output/spinner.ts

table.tsAdd table and detail renderers +45/-0

Add table and detail renderers

• Implements tabular and key/value detail output using cli-table3 with truncation for long fields.

src/lib/output/table.ts

yaml.tsAdd YAML output formatter +5/-0

Add YAML output formatter

• Implements YAML output formatting for users preferring yaml output mode.

src/lib/output/yaml.ts

prompts.tsWrap inquirer prompts with non-interactive fallbacks +123/-0

Wrap inquirer prompts with non-interactive fallbacks

• Adds prompt utilities (select/input/password/confirm) that degrade safely in CI/non-interactive environments.

src/lib/prompts.ts

sse-client.tsAdd SSE client with reconnection and protocol parsing +180/-0

Add SSE client with reconnection and protocol parsing

• Implements a fetch-based SSE client supporting event parsing, Last-Event-ID resume, exponential backoff reconnect, and clean shutdown.

src/lib/sse-client.ts

suggestions.tsProvide context-aware error suggestions and structured error format +96/-0

Provide context-aware error suggestions and structured error format

• Defines reusable suggestion text for auth/not-found/rate-limit scenarios and a machine-readable structured error shape for agent mode.

src/lib/suggestions.ts

.env.exampleAdd API integration template env example +2/-0

Add API integration template env example

• Provides example environment variables for the api-integration starter template.

templates/api-integration/.env.example

package.jsonAdd API integration template package manifest +17/-0

Add API integration template package manifest

• Defines dependencies and scripts for the api-integration starter template.

templates/api-integration/package.json

index.tsAdd API integration template entrypoint +24/-0

Add API integration template entrypoint

• Provides a starter TypeScript entrypoint demonstrating basic SDK usage for API integrations.

templates/api-integration/src/index.ts

.env.exampleAdd blank template env example +1/-0

Add blank template env example

• Provides minimal example env configuration for the blank starter template.

templates/blank/.env.example

package.jsonAdd blank template package manifest +17/-0

Add blank template package manifest

• Defines dependencies and scripts for the blank starter template.

templates/blank/package.json

index.tsAdd blank template entrypoint +16/-0

Add blank template entrypoint

• Adds a minimal starter entrypoint used by the blank template.

templates/blank/src/index.ts

.env.exampleAdd multi-camera template env example +1/-0

Add multi-camera template env example

• Provides example env configuration for the multi-camera starter template.

templates/multi-camera/.env.example

package.jsonAdd multi-camera template package manifest +17/-0

Add multi-camera template package manifest

• Defines dependencies and scripts for the multi-camera starter template.

templates/multi-camera/package.json

index.tsAdd multi-camera template entrypoint +49/-0

Add multi-camera template entrypoint

• Provides a starter implementation for multi-camera scenarios using the SDK.

templates/multi-camera/src/index.ts

.env.exampleAdd podcast template env example +1/-0

Add podcast template env example

• Provides example env configuration for the podcast starter template.

templates/podcast/.env.example

package.jsonAdd podcast template package manifest +17/-0

Add podcast template package manifest

• Defines dependencies and scripts for the podcast starter template.

templates/podcast/package.json

index.tsAdd podcast template entrypoint +33/-0

Add podcast template entrypoint

• Provides a starter entrypoint for podcast-related workflows using the SDK.

templates/podcast/src/index.ts

.env.exampleAdd SRT contribution template env example +1/-0

Add SRT contribution template env example

• Provides example env configuration for the SRT ingest/contribution template.

templates/srt-contribution/.env.example

package.jsonAdd SRT contribution template package manifest +17/-0

Add SRT contribution template package manifest

• Defines dependencies and scripts for the SRT contribution starter template.

templates/srt-contribution/package.json

index.tsAdd SRT contribution template entrypoint +29/-0

Add SRT contribution template entrypoint

• Provides a starter implementation targeting SRT ingest scenarios.

templates/srt-contribution/src/index.ts

.env.exampleAdd studio plugin template env example +2/-0

Add studio plugin template env example

• Provides example env configuration for the studio-plugin starter template.

templates/studio-plugin/.env.example

package.jsonAdd studio plugin template package manifest +17/-0

Add studio plugin template package manifest

• Defines dependencies and scripts for the studio-plugin starter template.

templates/studio-plugin/package.json

index.tsAdd studio plugin template entrypoint +32/-0

Add studio plugin template entrypoint

• Provides a starter entrypoint for building studio plugins.

templates/studio-plugin/src/index.ts

.env.exampleAdd webhook handler template env example +3/-0

Add webhook handler template env example

• Provides example env configuration for the webhook-handler starter template.

templates/webhook-handler/.env.example

package.jsonAdd webhook handler template package manifest +19/-0

Add webhook handler template package manifest

• Defines dependencies and scripts for an Express-based webhook handler template.

templates/webhook-handler/package.json

index.tsAdd webhook handler template entrypoint +52/-0

Add webhook handler template entrypoint

• Implements a starter webhook handler server entrypoint.

templates/webhook-handler/src/index.ts

.env.exampleAdd WebRTC demo template env example +1/-0

Add WebRTC demo template env example

• Provides example env configuration for the webrtc-demo starter template.

templates/webrtc-demo/.env.example

package.jsonAdd WebRTC demo template package manifest +17/-0

Add WebRTC demo template package manifest

• Defines dependencies and scripts for the WebRTC quickstart template.

templates/webrtc-demo/package.json

index.tsAdd WebRTC demo template entrypoint +31/-0

Add WebRTC demo template entrypoint

• Provides a starter entrypoint demonstrating WebRTC-centric workflows with the SDK.

templates/webrtc-demo/src/index.ts

Documentation (1) +98 / -0
RECOVERY.mdDocument source recovery and reproducible-build verification +98/-0

Document source recovery and reproducible-build verification

• Adds a detailed recovery note explaining sourcemap-based extraction and byte-identical rebuild verification for versions 1.0.0–1.0.8, including commands to reproduce the proof.

RECOVERY.md

Other (4) +110 / -0
.gitignoreIgnore build, package, and env artifacts +5/-0

Ignore build, package, and env artifacts

• Adds ignore rules for node_modules, dist output, packed tgz files, and local env files.

.gitignore

package.jsonRestore published @wave-av/cli manifest and dependencies +80/-0

Restore published @wave-av/cli manifest and dependencies

• Adds the npm package manifest (name/version/bin/files/scripts/engines) and runtime/dev dependencies needed to build and run the CLI as published.

package.json

tsconfig.jsonAdd strict TypeScript build configuration +15/-0

Add strict TypeScript build configuration

• Adds a strict ES2022/ESNext TypeScript configuration used to reproduce the published bundle.

tsconfig.json

tsup.config.tsAdd tsup build configuration to reproduce published dist +10/-0

Add tsup build configuration to reproduce published dist

• Defines tsup bundling settings (entry, ESM, node18 target, sourcemaps, clean, shebang banner) to rebuild dist/index.js identically.

tsup.config.ts

@cubic-dev-ai

cubic-dev-ai Bot commented Aug 5, 2026

Copy link
Copy Markdown

This PR has 6,617 reviewable changed lines after ignored/generated files are excluded, above this repository's 5,000-changed-line automatic review limit.

Most of the diff comes from:

  • src/commands/dev/index.ts (~256 changed lines)
  • src/commands/init/index.ts (~253 changed lines)
  • src/commands/link/index.ts (~218 changed lines)
  • src/lib/sse-client.ts (~180 changed lines)
  • src/cli.ts (~174 changed lines)

Comment @cubic-dev-ai review this to review it anyway. If the largest files are generated or fixture data, add them to your ignored files in review settings or ignorePatterns in cubic.yaml - cubic will then review the rest automatically. You can also raise this limit in review settings.

@devin-ai-integration devin-ai-integration 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.

Devin Review found 11 potential issues.

Open in Devin Review

Comment thread src/lib/sse-client.ts
Comment on lines +160 to +163
} else {
options.onError?.(new Error(`Max reconnect attempts (${maxAttempts}) exceeded`));
options.onClose?.();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 Event and log streaming commands hang forever after the connection ends

The streaming helper finishes without signalling shutdown (options.onClose?.() at src/lib/sse-client.ts:162) when the connection is given up on, so wave listen and wave logs tail print "Disconnected" and then sit there forever until the user kills them.
Impact: Users and scripts running these commands are left with a hung process that never exits on its own.

Abort controller is never triggered on non-user-initiated termination

src/commands/listen/index.ts:61-63 and src/commands/logs/index.ts:85-87 keep the command alive with await new Promise(resolve => controller.signal.addEventListener("abort", () => resolve())). The controller is only aborted by SIGINT/SIGTERM (src/lib/sse-client.ts:50-54). Two paths terminate the stream without aborting:

  1. Max reconnect attempts exceeded — options.onClose?.() is invoked at src/lib/sse-client.ts:162 but controller.abort() is never called.
  2. The server closes the stream cleanly — the read loop exits on done (src/lib/sse-client.ts:96), connect() returns normally, and no reconnect or close notification happens at all.

In both cases the awaited promise never settles and the SIGINT/SIGTERM listeners registered at src/lib/sse-client.ts:52-53 are also never removed.

Suggested change
} else {
options.onError?.(new Error(`Max reconnect attempts (${maxAttempts}) exceeded`));
options.onClose?.();
}
} else {
options.onError?.(new Error(`Max reconnect attempts (${maxAttempts}) exceeded`));
options.onClose?.();
controller.abort();
}
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread src/lib/config/manager.ts
Comment on lines +29 to +33
} catch {
const defaults = getDefaultConfig();
await saveConfig(defaults);
return defaults;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 Saved settings are silently wiped whenever the settings file cannot be read or fails validation

The stored settings file is replaced with a fresh default one (await saveConfig(defaults) at src/lib/config/manager.ts:30-31) as soon as reading or validating it fails, so a user's organization and project settings are permanently destroyed instead of being reported as a problem.
Impact: A single malformed or partially outdated settings file silently deletes all of the user's saved project configuration.

Catch-all recovery path overwrites the on-disk file

loadConfig() wraps both the JSON parse and the zod validation in one try. The schema at src/lib/config/schema.ts:3-8 requires organizationId and organizationName for every project entry, so any project written without those fields (e.g. by wave config set, which can inject arbitrary nested keys via setNestedValue in src/commands/config/index.ts:78-94) makes waveConfigSchema.parse throw. The catch block then writes defaults back over the file, discarding all existing projects. A non-destructive alternative is to return defaults in memory (and/or back up the bad file) without overwriting it, and surface an error to the user.

Prompt for agents
In src/lib/config/manager.ts, loadConfig() catches every failure (JSON parse error or zod validation error) and immediately calls saveConfig(defaults), overwriting the user's config.json on disk. This destroys all stored project/organization data whenever the file is malformed or fails the strict schema in src/lib/config/schema.ts. Consider returning the defaults in memory without persisting them, or renaming the offending file to a .bak before writing defaults, and surfacing a warning so the user knows their configuration was not loaded.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +184 to +191
// Generate .gitignore (append if template already has one)
const gitignorePath = join(dir, ".gitignore");
const gitignoreContent = `.env.local
.wave/
node_modules/
dist/
`;
await writeFile(gitignorePath, gitignoreContent, "utf-8");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Project scaffolding erases the starter project's ignore file

The newly created project's ignore file is unconditionally replaced (writeFile(gitignorePath, ...) at src/commands/init/index.ts:191) even when the starter files already provided one, so any ignore rules that shipped with the starter are lost.
Impact: Generated projects can accidentally commit files the template intended to keep out of version control.

Comment states append, implementation overwrites

The comment on src/commands/init/index.ts:184 explicitly says "append if template already has one", but copyDir (src/commands/init/index.ts:67-79) has already copied the template's .gitignore into dir, and the subsequent writeFile truncates it with the fixed four-line content. The link command implements the intended behaviour correctly via ensureGitignoreEntry (src/commands/link/index.ts:202-218), which reads and appends.

Prompt for agents
In src/commands/init/index.ts the generated .gitignore is written with writeFile, which overwrites any .gitignore that was copied from the template directory by copyDir, contradicting the adjacent comment ('append if template already has one'). Reuse an append-if-missing approach similar to ensureGitignoreEntry in src/commands/link/index.ts so template-provided ignore rules are preserved and the CLI-specific entries are only added when absent.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +10 to +13
.command("trigger <event>")
.description("Trigger a WAVE event manually")
.option("--override <pairs...>", "Override event data (key=value pairs)")
.option("--list", "List available trigger events")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Listing the available manual events is impossible without inventing an event name

The listing switch is attached to a command that demands an event name up front (.command("trigger <event>") at src/commands/trigger/index.ts:10), so running the documented listing form fails with a missing-argument error before it can do anything.
Impact: Users cannot discover which events they are allowed to trigger.

Required positional argument blocks the --list flag

Commander treats <event> as required, so wave trigger --list exits with "error: missing required argument 'event'". The --list branch at src/commands/trigger/index.ts:25-36 is only reachable with a throwaway value such as wave trigger x --list. Making the argument optional ([event]) and validating that it is present when --list is not passed would make the flag usable.

Suggested change
.command("trigger <event>")
.description("Trigger a WAVE event manually")
.option("--override <pairs...>", "Override event data (key=value pairs)")
.option("--list", "List available trigger events")
.command("trigger [event]")
.description("Trigger a WAVE event manually")
.option("--override <pairs...>", "Override event data (key=value pairs)")
.option("--list", "List available trigger events")
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +10 to +12
"dependencies": {
"@wave/sdk": "^2.0.0"
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Scaffolded starter projects fail to install their dependencies

Every starter project asks for a package that does not match the published one ("@wave/sdk": "^2.0.0" at templates/api-integration/package.json:11), so installing dependencies in a newly created project fails.
Impact: Projects created by the CLI cannot be installed or run out of the box.

Wrong scope on the SDK dependency in every template

The CLI itself depends on @wave-av/sdk (package.json:58), and the recovery notes discuss @wave-av/workflow-sdk, but all eight templates declare @wave/sdk and import from it: templates/api-integration/package.json:11, templates/blank/package.json:11, templates/multi-camera/package.json:11, templates/podcast/package.json:11, templates/srt-contribution/package.json:11, templates/studio-plugin/package.json:11, templates/webhook-handler/package.json:11, templates/webrtc-demo/package.json:11, plus the corresponding import { Wave } from "@wave/sdk" lines in each src/index.ts. wave init copies these files and then runs npm install (src/commands/init/index.ts:227-237), which throws with the npm stderr.

Prompt for agents
All templates under templates/ declare and import '@wave/sdk' while the CLI and the published ecosystem use '@wave-av/sdk' (see package.json dependencies). Because `wave init` copies a template and then runs `npm install` (src/commands/init/index.ts), scaffolded projects fail to install. Update the dependency name and the import statements in each template's package.json and src/index.ts to the correct scope, and verify the API surface used in each sample still matches the SDK.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread src/cli.ts
program
.name("wave")
.description("WAVE CLI - Command-line interface for the WAVE streaming platform")
.version("1.0.0", "-v, --version")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 The CLI reports the wrong version number

The version reported to users is hardcoded to an old value (.version("1.0.0", "-v, --version") at src/cli.ts:82) while the package being shipped is 1.0.8, so wave --version misinforms anyone checking which release they have.
Impact: Bug reports and support requests will cite a version that does not match the installed release.

Three hardcoded 1.0.0 strings vs package.json 1.0.8

package.json:3 declares "version": "1.0.8". The literal 1.0.0 is hardcoded in the version flag (src/cli.ts:82), the banner (src/cli.ts:71), the raw-request User-Agent (src/commands/api/index.ts:34) and the SDK header X-Wave-CLI-Version (src/lib/api-client.ts:49), so server-side telemetry also attributes all traffic to 1.0.0. Reading the version from the manifest at build time would keep these in sync.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread src/lib/auth/keychain.ts
Comment on lines +13 to +24
async function getKeytar(): Promise<KeytarLike | null> {
if (keytarChecked) return keytarModule;
keytarChecked = true;
try {
keytarModule = (await import(
/* webpackIgnore: true */ "keytar" as string
)) as unknown as KeytarLike;
return keytarModule;
} catch {
return null;
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔍 Keytar is loaded via a dynamic import that may not expose named CJS exports

getKeytar() does (await import("keytar" as string)) as unknown as KeytarLike and then calls keytar.setPassword(...) directly on the module namespace. keytar is a CommonJS native addon; Node's cjs-module-lexer usually surfaces named exports for such modules, but for native .node-backed bindings the named-export detection can fail, in which case the functions live only under .default and keytar.setPassword would be undefined at runtime — which throws a TypeError rather than falling through to the file-based fallback (the try/catch only covers the import itself, not the call). Worth verifying against the actual keytar build before relying on it; a mod.default ?? mod normalisation would be safer.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread src/commands/api/index.ts
Comment on lines +27 to +35
const url = path.startsWith("http")
? path
: `${baseUrl}${path.startsWith("/") ? path : `/${path}`}`;

const headers: Record<string, string> = {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
"User-Agent": "wave-cli/1.0.0",
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟨 Raw API command sends the stored bearer token to any absolute URL supplied on the command line

wave api <method> <path> accepts an absolute URL (path.startsWith("http") at src/commands/api/index.ts:27-29) and unconditionally attaches Authorization: Bearer ${apiKey} (src/commands/api/index.ts:31-35). A user pasting a command from an untrusted source, or a script/agent constructing the path from untrusted input, will transmit the account's long-lived API key to an arbitrary third-party host. The same code also permits plain http:// URLs, sending the credential in cleartext.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +78 to +94
function setNestedValue(obj: Record<string, unknown>, path: string, value: string): void {
const keys = path.split(".");
let current: Record<string, unknown> = obj;
for (let i = 0; i < keys.length - 1; i++) {
const key = keys[i];
if (typeof current[key] !== "object" || current[key] === null) {
current[key] = {};
}
current = current[key] as Record<string, unknown>;
}
const lastKey = keys[keys.length - 1];
// Auto-parse booleans and numbers
if (value === "true") current[lastKey] = true;
else if (value === "false") current[lastKey] = false;
else if (!isNaN(Number(value)) && value !== "") current[lastKey] = Number(value);
else current[lastKey] = value;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟨 Configuration setter allows writing to prototype keys

setNestedValue in src/commands/config/index.ts:78-94 splits a user-supplied dotted key and walks/creates nested objects with no key filtering, so wave config set __proto__.polluted x or wave config set constructor.prototype.x y writes onto Object.prototype for the remainder of the process and persists the crafted structure into ~/.wave/config.json, where it is re-parsed on every later invocation.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +55 to +66
if (envKey) {
checks.push({
name: "Auth",
status: "pass",
message: `WAVE_API_KEY env var set (${envKey.slice(0, 12)}...)`,
});
} else if (apiKey) {
checks.push({
name: "Auth",
status: "pass",
message: `API key stored for "${config.currentProject}" (${apiKey.slice(0, 12)}...)`,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟨 Diagnostics command prints a prefix of the live API key to the terminal

wave doctor echoes the first 12 characters of the API key from the keychain and of WAVE_API_KEY (src/commands/doctor/index.ts:55-66). Diagnostic output is routinely pasted into issue trackers, chat and CI logs, so a meaningful prefix of a live credential ends up in places it should not be.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (12) 📘 Rule violations (1) 📜 Skill insights (0)

Grey Divider


Action required

1. lint script missing eslint 📘 Rule violation ✧ Quality
Description
package.json defines lint as eslint src/, but eslint is not listed in dependencies or
devDependencies, so npm run lint will fail in CI on a clean install. This introduces a
deterministic new CI failure risk for the configured lint command.
Code

package.json[R20-23]

+    "test": "vitest run",
+    "test:watch": "vitest",
+    "lint": "eslint src/",
+    "prepublishOnly": "npm run build"
Evidence
The compliance rule requires that configured CI commands like npm run lint succeed. The PR adds a
lint script that calls eslint, but the same file shows no eslint dependency, meaning the
command will fail with a missing binary/module on a fresh install.

Rule 2497928: Changed code must not introduce new lint, type, or test failures in the existing CI configuration
package.json[16-23]
package.json[71-79]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`npm run lint` is configured to run `eslint src/`, but the `eslint` package is not installed via `package.json`, causing lint to fail in CI/clean environments.

## Issue Context
Compliance requires that changed code must not introduce new lint/type/test failures in the existing CI configuration. Since the `lint` script invokes `eslint`, the repo should declare `eslint` (and any required config) so the command can run successfully.

## Fix Focus Areas
- package.json[16-23]
- package.json[71-79]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Login leaves project unusable 🐞 Bug ≡ Correctness
Description
auth login stores a credential and changes currentProject without creating the corresponding
config.projects entry. On a fresh install, getClient() rejects that missing entry before reading
the stored key, blocking SDK commands and even wave link.
Code

src/commands/auth/index.ts[R40-43]

+        await updateConfig((config) => ({
+          ...config,
+          currentProject: project,
+        }));
Evidence
The default schema creates an empty projects map, while login only stores the key/current name.
getClient() then exits when that project entry is absent, and link calls getClient() before it
can populate the project.

src/commands/auth/index.ts[17-43]
src/lib/config/schema.ts[10-20]
src/lib/api-client.ts[20-40]
src/commands/link/index.ts[41-54]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Login stores credentials for a project that is absent from `config.projects`, so authenticated SDK commands immediately reject it.

## Issue Context
Both API-key and device-flow login paths must establish the project invariant expected by `getClient()`. Populate required organization fields from the authentication response where available, or allow a key-only default project safely.

## Fix Focus Areas
- src/commands/auth/index.ts[17-43]
- src/lib/api-client.ts[20-46]
- src/lib/config/schema.ts[3-20]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Bundled init misses templates 🐞 Bug ≡ Correctness
Description
getTemplatesDir() walks up three levels as though the runtime file remains under
dist/commands/init, but tsup emits the bundled entry as dist/index.js. Installed builds
therefore resolve outside the package, skip the shipped template, and produce an incomplete fallback
project without its package manifest or source file.
Code

src/commands/init/index.ts[R57-60]

+  const thisFile = fileURLToPath(import.meta.url);
+  // Walk up from src/commands/init/ or dist/commands/init/ to package root
+  const packageRoot = resolve(dirname(thisFile), "..", "..", "..");
+  return join(packageRoot, "templates");
Evidence
The build has one src/index.ts entry that becomes dist/index.js; from that file's directory,
three parent traversals cannot identify the package root. The missing-directory branch creates only
src, whereas the package explicitly ships complete templates.

src/commands/init/index.ts[52-79]
src/commands/init/index.ts[145-168]
tsup.config.ts[3-9]
package.json[10-14]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The runtime template path assumes an unbundled module layout and points outside the package after tsup bundles the CLI.

## Issue Context
Templates are shipped beside `dist` at the package root. Resolve assets relative to the actual bundled `dist/index.js` location or inject a stable package-root path, and fail clearly rather than creating an unusable partial scaffold.

## Fix Focus Areas
- src/commands/init/index.ts[52-79]
- src/commands/init/index.ts[145-168]
- tsup.config.ts[3-9]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (4)
4. API key sent off-host 🐞 Bug ⛨ Security
Description
wave api accepts any absolute HTTP URL and unconditionally attaches the stored WAVE bearer token.
Supplying an attacker-controlled URL therefore discloses the credential outside the configured API
host.
Code

src/commands/api/index.ts[R27-29]

+        const url = path.startsWith("http")
+          ? path
+          : `${baseUrl}${path.startsWith("/") ? path : `/${path}`}`;
Evidence
The user-controlled path is used directly whenever it starts with http, and the request options
always contain Authorization: Bearer <stored key> before fetch is called.

src/commands/api/index.ts[26-35]
src/commands/api/index.ts[45-54]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The raw API command forwards the stored bearer token to arbitrary absolute URLs.

## Issue Context
Relative paths should resolve against the configured WAVE base URL. Reject off-host absolute URLs, or require explicit opt-in and omit credentials; also enforce an approved HTTPS scheme.

## Fix Focus Areas
- src/commands/api/index.ts[26-35]
- src/commands/api/index.ts[45-54]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Clean SSE EOF hangs 🐞 Bug ☼ Reliability
Description
A normal SSE response EOF breaks the reader loop without reconnecting, invoking onClose, or
aborting the controller. listen and logs tail then remain blocked waiting only for an abort
while the dead stream can deliver no more events.
Code

src/lib/sse-client.ts[R94-96]

+      while (!controller.signal.aborted) {
+        const { done, value } = await reader.read();
+        if (done) break;
Evidence
Reconnect logic exists only in the catch branch, but done merely breaks the loop and returns
normally. Both callers await the controller's abort event, which EOF never triggers.

src/lib/sse-client.ts[94-164]
src/commands/listen/index.ts[61-63]
src/commands/logs/index.ts[85-87]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Clean server-side stream closure bypasses all reconnect and close handling, leaving streaming commands hung.

## Issue Context
Treat EOF as a disconnect: either enter the bounded reconnect path or close/abort the controller so callers resolve. Ensure callbacks and signal-handler cleanup occur exactly once.

## Fix Focus Areas
- src/lib/sse-client.ts[94-164]
- src/commands/listen/index.ts[61-63]
- src/commands/logs/index.ts[85-87]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Templates depend on non-existent @wave/sdk package 🐞 Bug ≡ Correctness
Description
All eight scaffold templates (webrtc-demo, srt-contribution, webhook-handler, api-integration,
studio-plugin, blank, multi-camera, podcast) import and depend on @wave/sdk, but the CLI,
documentation, and generated configuration identify the SDK as @wave-av/sdk. As a result, running
wave init with any of these templates and then npm install will fail to resolve the intended
dependency or may install an unrelated package, breaking the generated project out of the box.
Code

templates/webhook-handler/package.json[R10-12]

+  "dependencies": {
+    "@wave/sdk": "^2.0.0",
+    "express": "^4.21.0"
Evidence
The repository’s CLI code and dependencies consistently reference @wave-av/sdk (e.g., the root
package.json depends on it and src/lib/api-client.ts imports Wave from @wave-av/sdk), and
init also generates configuration that imports the same package; however, the scaffold templates’
manifests and sources (their package.json files and src/index.ts entrypoints) consistently use
@wave/sdk instead. This direct package-name mismatch between what the CLI/docs/config expect and
what templates declare proves that newly generated projects will not install the advertised SDK when
users run npm install.

src/lib/api-client.ts[1-8]
package.json[57-59]
templates/webhook-handler/package.json[10-12]
templates/webhook-handler/src/index.ts[1-9]
templates/blank/package.json[10-15]
templates/blank/src/index.ts[1-4]
templates/webhook-handler/package.json[10-17]
README.md[176-180]
src/commands/init/index.ts[170-175]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
All scaffold template projects reference `@wave/sdk` in their `package.json` dependencies and source imports instead of the intended/published `@wave-av/sdk` package used by the CLI, docs, and generated `wave.config.ts`. This mismatch causes `npm install` to fail (package not found) or to install an incorrect/unrelated package, leaving projects generated by `wave init` broken by default.

## Issue Context
The CLI’s own dependencies and code paths already use `@wave-av/sdk` (including `package.json` and files like `src/lib/api-client.ts`, `src/lib/errors.ts`), and `wave init` copies `templates/*` verbatim into the user’s new project (see `src/commands/init/index.ts`). Update every template manifest and source import to consistently use `@wave-av/sdk`, then install and type-check each generated template to confirm everything resolves correctly.

## Fix Focus Areas
- templates/webhook-handler/package.json[10-12]
- templates/webhook-handler/src/index.ts[1-9]
- templates/api-integration/package.json[10-12]
- templates/blank/package.json[10-12]
- templates/blank/package.json[10-15]
- templates/blank/src/index.ts[1-4]
- templates/multi-camera/package.json[10-12]
- templates/podcast/package.json[10-12]
- templates/srt-contribution/package.json[10-12]
- templates/studio-plugin/package.json[10-12]
- templates/webrtc-demo/package.json[10-12]
- templates/webhook-handler/package.json[10-17]
- templates/webhook-handler/src/index.ts[1-5]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. Recovered auth/config code imports missing types module 🐞 Bug ≡ Correctness
Description
src/lib/auth/device-flow.ts, src/lib/config/manager.ts, and src/lib/output/index.ts import
type declarations from ../../types/index.js / src/types/index.js, but no src/types module
exists in the recovered source tree. As a result, tsc --noEmit / tsup (and thus `npm run
type-check / npm run build`) fail on unresolved module imports, undermining the PR’s reproducible,
buildable recovery claim.
Code

src/lib/auth/device-flow.ts[11]

+import type { DeviceAuthResponse, TokenResponse } from "../../types/index.js";
Evidence
The cited files (device-flow.ts, config/manager.ts, and output/index.ts) each contain imports
that point at a shared types entrypoint (types/index.js), yet the repository contents under src/
do not include any src/types/ directory or types/index file—only cli.ts, commands/,
index.ts, and lib/ are present. Because the project’s tsconfig is strict and includes all src
files and the package exposes a tsc --noEmit type-check script, these missing-module imports
necessarily break npm run type-check and the documented verification flow in RECOVERY.md (`npm
ci --include=dev && npx tsup`), which requires all imports to resolve.

src/lib/auth/device-flow.ts[11-11]
src/lib/config/manager.ts[5-5]
src/lib/output/index.ts[1-1]
src/lib/config/manager.ts[5-6]
tsconfig.json[11-14]
package.json[16-23]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Several recovered source files import type-only symbols from a shared `types/index` module (e.g., `DeviceAuthResponse`, `TokenResponse`, `WaveConfig`, `OutputFormat`), but the repository does not contain the corresponding `src/types` tree/module, causing TypeScript module resolution failures during `tsc --noEmit`/`tsup`.

## Issue Context
This breaks the PR’s core reproducible-build assertion: the documented verification steps in `RECOVERY.md` (`npm ci --include=dev && npx tsup`) and the added/available `npm run type-check` rely on `tsconfig` including all `src` files and on every import resolving successfully. To restore buildability, either add the missing `src/types/index.ts` (or equivalent) exporting the required types, or re-point these imports to existing sources (schemas/modules) that already define them, then confirm the full repo passes the type-check script.

## Fix Focus Areas
- src/lib/auth/device-flow.ts[11-11]
- src/lib/config/manager.ts[5-6]
- src/lib/output/index.ts[1-1]
- tsconfig.json[11-14]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

8. Recovery command cannot install 🐞 Bug ⚙ Maintainability
Description
RECOVERY.md instructs auditors to run npm ci, but the recovered repository has no npm lockfile.
The command stops before tsup runs, so the documented byte-comparison procedure is not reproducible
as written.
Code

RECOVERY.md[R53-55]

+# 3. build and compare
+npm ci --include=dev && npx tsup
+cmp dist/index.js package/dist/index.js && echo IDENTICAL
Evidence
The recovery instructions explicitly invoke npm ci, while the added dependency manifest is the
only npm installation input in the repository and no lockfile accompanies it.

RECOVERY.md[34-58]
package.json[57-79]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The documented recovery procedure uses `npm ci` without the lockfile that command requires.

## Issue Context
Commit the matching npm lockfile and validate the full commands from a clean checkout. If a lockfile cannot be recovered, document a tested package-manager/version procedure that actually runs and explain its reproducibility limits.

## Fix Focus Areas
- RECOVERY.md[34-58]
- package.json[57-79]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


9. Template env file ignored 🐞 Bug ≡ Correctness
Description
Generated instructions tell users to place credentials in .env.local, but template dev scripts
launch tsx without loading that file and the code only reads process.env. Following the
generated README therefore starts templates with an undefined API key unless users separately export
it.
Code

templates/blank/package.json[R6-8]

+  "scripts": {
+    "dev": "npx tsx src/index.ts",
+    "build": "tsc"
Evidence
Init writes .env.local guidance and tells users to run npm run dev; the template dev command
only invokes tsx, has no env-loader dependency, and reads the key directly from the process
environment.

src/commands/init/index.ts[184-209]
templates/blank/package.json[6-15]
templates/blank/src/index.ts[3-5]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Generated templates do not load the `.env.local` file that their generated README instructs users to create.

## Issue Context
Add an environment loader/preload to every template or change the scripts and documentation to use a supported env-file mechanism. Validate `npm run dev` using only the documented setup steps.

## Fix Focus Areas
- templates/blank/package.json[6-15]
- templates/blank/src/index.ts[3-5]
- src/commands/init/index.ts[184-209]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


10. Authentication fixes are invalid 🐞 Bug ≡ Correctness
Description
Multiple error and onboarding messages instruct users to run wave login, but the only registered
login command is wave auth login. Following the displayed remediation produces an unknown-command
error instead of restoring authentication.
Code

src/lib/api-client.ts[R25-28]

+    console.error(
+      chalk.red(
+        `No project "${projectName}" configured. Run ${chalk.bold("wave login")} to authenticate.`,
+      ),
Evidence
Login is registered only beneath the auth command. Nevertheless, shared client failures,
structured suggestions, doctor output, and generated init instructions refer to the nonexistent
top-level form.

src/commands/auth/index.ts[9-15]
src/lib/api-client.ts[23-40]
src/lib/errors.ts[43-49]
src/commands/doctor/index.ts[68-85]
src/commands/init/index.ts[242-250]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Authentication remediation points to a top-level command that the CLI does not register.

## Issue Context
Either add a top-level `login` alias that delegates to `auth login`, or update all errors, suggestions, doctor fixes, and generated next steps to consistently use `wave auth login`.

## Fix Focus Areas
- src/commands/auth/index.ts[9-15]
- src/lib/api-client.ts[23-40]
- src/lib/errors.ts[43-49]
- src/commands/init/index.ts[242-250]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (1)
11. Plaintext credential fallback lacks hardened permissions 🐞 Bug ⛨ Security
Description
When the optional native keytar module cannot be loaded, storeApiKey/getApiKey silently fall
back to writing bearer API keys as plaintext JSON in ~/.wave/credentials.json. The containing
directory is created with mkdir(dir, { recursive: true }) without an explicit restrictive mode
(left to the process umask) and no warning is emitted to the user that credentials are stored
unencrypted on disk.
Code

src/lib/auth/keychain.ts[R82-96]

+async function saveCredentials(creds: Record<string, string>): Promise<void> {
+  const dir = join(homedir(), ".wave");
+  if (!existsSync(dir)) {
+    await mkdir(dir, { recursive: true });
+  }
+  await writeFile(CRED_FILE, JSON.stringify(creds, null, 2), {
+    mode: 0o600,
+  });
+}
+
+async function storeToFile(project: string, key: string): Promise<void> {
+  const creds = await loadCredentials();
+  creds[project] = key;
+  await saveCredentials(creds);
+}
Evidence
The new file-based fallback (added in this PR) is the only place credentials are persisted when
keytar is unavailable; the directory creation omits an explicit mode and the file write, while using
mode 0o600, does not retroactively fix permissions on a pre-existing directory or file, and no
diagnostic is surfaced to the user about the reduced security posture.

src/lib/auth/keychain.ts[70-107]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
When the optional `keytar` native module cannot be loaded, the CLI falls back to storing API keys as plaintext JSON at `~/.wave/credentials.json`. The fallback directory is created without an explicit restrictive mode, and the user is never told their credentials are stored unencrypted.

## Issue Context
This is a newly added fallback path introduced in this PR (`src/lib/auth/keychain.ts`). It is exercised whenever the dynamic `import("keytar")` throws (e.g., missing native binary, unsupported platform), which is a realistic scenario for many CLI users.

## Fix Focus Areas
- src/lib/auth/keychain.ts[82-89] (saveCredentials: harden directory creation with `mkdir(dir, { recursive: true, mode: 0o700 })` and consider explicitly `chmod`-ing an already-existing directory/file to 0o700/0o600)
- src/lib/auth/keychain.ts[26-33] (storeApiKey: emit a one-time warning to stderr when falling back to file storage instead of the OS keychain)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

12. CLI reports stale version 🐞 Bug ◔ Observability
Description
The package is version 1.0.8, but --version, the banner, User-Agent, and CLI request header all
report 1.0.0. This makes installed-version diagnostics and server-side request attribution
inaccurate.
Code

src/cli.ts[R79-83]

+  program
+    .name("wave")
+    .description("WAVE CLI - Command-line interface for the WAVE streaming platform")
+    .version("1.0.0", "-v, --version")
+    .option("-o, --output <format>", "Output format: table, json, yaml", "table")
Evidence
The manifest declares 1.0.8, while all cited CLI and HTTP identification fields contain the 1.0.0
literal.

package.json[1-3]
src/cli.ts[71-83]
src/lib/api-client.ts[43-50]
src/commands/api/index.ts[31-35]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
User-facing output and request metadata hardcode an obsolete version.

## Issue Context
Use a single build-time or runtime version source derived from the package manifest for Commander, the banner, User-Agent, and custom headers.

## Fix Focus Areas
- src/cli.ts[71-83]
- src/lib/api-client.ts[43-50]
- src/commands/api/index.ts[31-35]
- package.json[1-3]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


13. SSE client accumulates duplicate SIGINT/SIGTERM listeners 🐞 Bug ☼ Reliability
Description
connectSSE registers its own process-level SIGINT/SIGTERM listeners on every call, and the
dev command invokes connectSSE twice (for webhook and log streams) while also registering its
own shutdown signal handlers, resulting in multiple overlapping signal handlers for a single command
invocation. This can trigger Node's MaxListenersExceededWarning and lead to ambiguous or duplicated
shutdown behavior.
Code

src/lib/sse-client.ts[R53-55]

+  process.on("SIGINT", cleanup);
+  process.on("SIGTERM", cleanup);
+
Evidence
src/commands/dev/index.ts calls connectSSE twice (webhookController and logController), each
invocation of connectSSE independently calls process.on("SIGINT", cleanup) and process.on("SIGTERM",
cleanup) at lines 53-55 of sse-client.ts, and dev/index.ts itself also registers its own
SIGINT/SIGTERM handlers for the shutdown promise, resulting in multiple overlapping process-level
signal handlers for one command.

src/lib/sse-client.ts[53-55]
src/commands/dev/index.ts[165-246]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Each call to `connectSSE` registers its own `SIGINT`/`SIGTERM` process-level listeners. The `dev` command invokes `connectSSE` twice and also registers its own signal handlers for shutdown, leading to multiple overlapping handlers for a single command invocation.

## Issue Context
This is a minor reliability/maintainability concern; Node tolerates multiple listeners up to a default warning threshold, but the pattern is fragile for commands that open more than a couple of SSE connections.

## Fix Focus Areas
- src/lib/sse-client.ts[53-55] (signal handler registration inside connectSSE)
- src/commands/dev/index.ts[238-246] (duplicate SIGINT/SIGTERM registration in the dev command)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context used
✅ Compliance rules (platform): 2 rules
✅ REVIEW.md
Review mode: 🧠 Deep: This restores substantial executable CLI logic across dozens of independent command and library paths, creating a dense set of easy-to-miss behavioral and security defects despite the claimed byte-identical builds.
ⓘ  11 issues published inline · 13 in summary

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment thread package.json
Comment on lines +20 to +23
"test": "vitest run",
"test:watch": "vitest",
"lint": "eslint src/",
"prepublishOnly": "npm run build"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. lint script missing eslint 📘 Rule violation ✧ Quality

package.json defines lint as eslint src/, but eslint is not listed in dependencies or
devDependencies, so npm run lint will fail in CI on a clean install. This introduces a
deterministic new CI failure risk for the configured lint command.
Agent Prompt
## Issue description
`npm run lint` is configured to run `eslint src/`, but the `eslint` package is not installed via `package.json`, causing lint to fail in CI/clean environments.

## Issue Context
Compliance requires that changed code must not introduce new lint/type/test failures in the existing CI configuration. Since the `lint` script invokes `eslint`, the repo should declare `eslint` (and any required config) so the command can run successfully.

## Fix Focus Areas
- package.json[16-23]
- package.json[71-79]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +40 to +43
await updateConfig((config) => ({
...config,
currentProject: project,
}));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

2. Login leaves project unusable 🐞 Bug ≡ Correctness

auth login stores a credential and changes currentProject without creating the corresponding
config.projects entry. On a fresh install, getClient() rejects that missing entry before reading
the stored key, blocking SDK commands and even wave link.
Agent Prompt
## Issue description
Login stores credentials for a project that is absent from `config.projects`, so authenticated SDK commands immediately reject it.

## Issue Context
Both API-key and device-flow login paths must establish the project invariant expected by `getClient()`. Populate required organization fields from the authentication response where available, or allow a key-only default project safely.

## Fix Focus Areas
- src/commands/auth/index.ts[17-43]
- src/lib/api-client.ts[20-46]
- src/lib/config/schema.ts[3-20]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +57 to +60
const thisFile = fileURLToPath(import.meta.url);
// Walk up from src/commands/init/ or dist/commands/init/ to package root
const packageRoot = resolve(dirname(thisFile), "..", "..", "..");
return join(packageRoot, "templates");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

3. Bundled init misses templates 🐞 Bug ≡ Correctness

getTemplatesDir() walks up three levels as though the runtime file remains under
dist/commands/init, but tsup emits the bundled entry as dist/index.js. Installed builds
therefore resolve outside the package, skip the shipped template, and produce an incomplete fallback
project without its package manifest or source file.
Agent Prompt
## Issue description
The runtime template path assumes an unbundled module layout and points outside the package after tsup bundles the CLI.

## Issue Context
Templates are shipped beside `dist` at the package root. Resolve assets relative to the actual bundled `dist/index.js` location or inject a stable package-root path, and fail clearly rather than creating an unusable partial scaffold.

## Fix Focus Areas
- src/commands/init/index.ts[52-79]
- src/commands/init/index.ts[145-168]
- tsup.config.ts[3-9]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread src/commands/api/index.ts
Comment on lines +27 to +29
const url = path.startsWith("http")
? path
: `${baseUrl}${path.startsWith("/") ? path : `/${path}`}`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

4. Api key sent off-host 🐞 Bug ⛨ Security

wave api accepts any absolute HTTP URL and unconditionally attaches the stored WAVE bearer token.
Supplying an attacker-controlled URL therefore discloses the credential outside the configured API
host.
Agent Prompt
## Issue description
The raw API command forwards the stored bearer token to arbitrary absolute URLs.

## Issue Context
Relative paths should resolve against the configured WAVE base URL. Reject off-host absolute URLs, or require explicit opt-in and omit credentials; also enforce an approved HTTPS scheme.

## Fix Focus Areas
- src/commands/api/index.ts[26-35]
- src/commands/api/index.ts[45-54]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread src/lib/sse-client.ts
Comment on lines +94 to +96
while (!controller.signal.aborted) {
const { done, value } = await reader.read();
if (done) break;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

5. Clean sse eof hangs 🐞 Bug ☼ Reliability

A normal SSE response EOF breaks the reader loop without reconnecting, invoking onClose, or
aborting the controller. listen and logs tail then remain blocked waiting only for an abort
while the dead stream can deliver no more events.
Agent Prompt
## Issue description
Clean server-side stream closure bypasses all reconnect and close handling, leaving streaming commands hung.

## Issue Context
Treat EOF as a disconnect: either enter the bounded reconnect path or close/abort the controller so callers resolve. Ensure callbacks and signal-handler cleanup occur exactly once.

## Fix Focus Areas
- src/lib/sse-client.ts[94-164]
- src/commands/listen/index.ts[61-63]
- src/commands/logs/index.ts[85-87]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +6 to +8
"scripts": {
"dev": "npx tsx src/index.ts",
"build": "tsc"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

7. Template env file ignored 🐞 Bug ≡ Correctness

Generated instructions tell users to place credentials in .env.local, but template dev scripts
launch tsx without loading that file and the code only reads process.env. Following the
generated README therefore starts templates with an undefined API key unless users separately export
it.
Agent Prompt
## Issue description
Generated templates do not load the `.env.local` file that their generated README instructs users to create.

## Issue Context
Add an environment loader/preload to every template or change the scripts and documentation to use a supported env-file mechanism. Validate `npm run dev` using only the documented setup steps.

## Fix Focus Areas
- templates/blank/package.json[6-15]
- templates/blank/src/index.ts[3-5]
- src/commands/init/index.ts[184-209]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread src/lib/api-client.ts
Comment on lines +25 to +28
console.error(
chalk.red(
`No project "${projectName}" configured. Run ${chalk.bold("wave login")} to authenticate.`,
),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

9. Authentication fixes are invalid 🐞 Bug ≡ Correctness

Multiple error and onboarding messages instruct users to run wave login, but the only registered
login command is wave auth login. Following the displayed remediation produces an unknown-command
error instead of restoring authentication.
Agent Prompt
## Issue description
Authentication remediation points to a top-level command that the CLI does not register.

## Issue Context
Either add a top-level `login` alias that delegates to `auth login`, or update all errors, suggestions, doctor fixes, and generated next steps to consistently use `wave auth login`.

## Fix Focus Areas
- src/commands/auth/index.ts[9-15]
- src/lib/api-client.ts[23-40]
- src/lib/errors.ts[43-49]
- src/commands/init/index.ts[242-250]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread src/lib/auth/keychain.ts
Comment on lines +82 to +96
async function saveCredentials(creds: Record<string, string>): Promise<void> {
const dir = join(homedir(), ".wave");
if (!existsSync(dir)) {
await mkdir(dir, { recursive: true });
}
await writeFile(CRED_FILE, JSON.stringify(creds, null, 2), {
mode: 0o600,
});
}

async function storeToFile(project: string, key: string): Promise<void> {
const creds = await loadCredentials();
creds[project] = key;
await saveCredentials(creds);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Remediation recommended

10. Plaintext credential fallback lacks hardened permissions 🐞 Bug ⛨ Security

When the optional native keytar module cannot be loaded, storeApiKey/getApiKey silently fall
back to writing bearer API keys as plaintext JSON in ~/.wave/credentials.json. The containing
directory is created with mkdir(dir, { recursive: true }) without an explicit restrictive mode
(left to the process umask) and no warning is emitted to the user that credentials are stored
unencrypted on disk.
Agent Prompt
## Issue description
When the optional `keytar` native module cannot be loaded, the CLI falls back to storing API keys as plaintext JSON at `~/.wave/credentials.json`. The fallback directory is created without an explicit restrictive mode, and the user is never told their credentials are stored unencrypted.

## Issue Context
This is a newly added fallback path introduced in this PR (`src/lib/auth/keychain.ts`). It is exercised whenever the dynamic `import("keytar")` throws (e.g., missing native binary, unsupported platform), which is a realistic scenario for many CLI users.

## Fix Focus Areas
- src/lib/auth/keychain.ts[82-89] (saveCredentials: harden directory creation with `mkdir(dir, { recursive: true, mode: 0o700 })` and consider explicitly `chmod`-ing an already-existing directory/file to 0o700/0o600)
- src/lib/auth/keychain.ts[26-33] (storeApiKey: emit a one-time warning to stderr when falling back to file storage instead of the OS keychain)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +10 to +12
"dependencies": {
"@wave/sdk": "^2.0.0",
"express": "^4.21.0"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

11. Templates depend on non-existent @wave/sdk package 🐞 Bug ≡ Correctness

All eight scaffold templates (webrtc-demo, srt-contribution, webhook-handler, api-integration,
studio-plugin, blank, multi-camera, podcast) import and depend on @wave/sdk, but the CLI,
documentation, and generated configuration identify the SDK as @wave-av/sdk. As a result, running
wave init with any of these templates and then npm install will fail to resolve the intended
dependency or may install an unrelated package, breaking the generated project out of the box.
Agent Prompt
## Issue description
All scaffold template projects reference `@wave/sdk` in their `package.json` dependencies and source imports instead of the intended/published `@wave-av/sdk` package used by the CLI, docs, and generated `wave.config.ts`. This mismatch causes `npm install` to fail (package not found) or to install an incorrect/unrelated package, leaving projects generated by `wave init` broken by default.

## Issue Context
The CLI’s own dependencies and code paths already use `@wave-av/sdk` (including `package.json` and files like `src/lib/api-client.ts`, `src/lib/errors.ts`), and `wave init` copies `templates/*` verbatim into the user’s new project (see `src/commands/init/index.ts`). Update every template manifest and source import to consistently use `@wave-av/sdk`, then install and type-check each generated template to confirm everything resolves correctly.

## Fix Focus Areas
- templates/webhook-handler/package.json[10-12]
- templates/webhook-handler/src/index.ts[1-9]
- templates/api-integration/package.json[10-12]
- templates/blank/package.json[10-12]
- templates/blank/package.json[10-15]
- templates/blank/src/index.ts[1-4]
- templates/multi-camera/package.json[10-12]
- templates/podcast/package.json[10-12]
- templates/srt-contribution/package.json[10-12]
- templates/studio-plugin/package.json[10-12]
- templates/webrtc-demo/package.json[10-12]
- templates/webhook-handler/package.json[10-17]
- templates/webhook-handler/src/index.ts[1-5]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


import open from "open";
import chalk from "chalk";
import type { DeviceAuthResponse, TokenResponse } from "../../types/index.js";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

12. Recovered auth/config code imports missing types module 🐞 Bug ≡ Correctness

src/lib/auth/device-flow.ts, src/lib/config/manager.ts, and src/lib/output/index.ts import
type declarations from ../../types/index.js / src/types/index.js, but no src/types module
exists in the recovered source tree. As a result, tsc --noEmit / tsup (and thus `npm run
type-check / npm run build`) fail on unresolved module imports, undermining the PR’s reproducible,
buildable recovery claim.
Agent Prompt
## Issue description
Several recovered source files import type-only symbols from a shared `types/index` module (e.g., `DeviceAuthResponse`, `TokenResponse`, `WaveConfig`, `OutputFormat`), but the repository does not contain the corresponding `src/types` tree/module, causing TypeScript module resolution failures during `tsc --noEmit`/`tsup`.

## Issue Context
This breaks the PR’s core reproducible-build assertion: the documented verification steps in `RECOVERY.md` (`npm ci --include=dev && npx tsup`) and the added/available `npm run type-check` rely on `tsconfig` including all `src` files and on every import resolving successfully. To restore buildability, either add the missing `src/types/index.ts` (or equivalent) exporting the required types, or re-point these imports to existing sources (schemas/modules) that already define them, then confirm the full repo passes the type-check script.

## Fix Focus Areas
- src/lib/auth/device-flow.ts[11-11]
- src/lib/config/manager.ts[5-6]
- src/lib/output/index.ts[1-1]
- tsconfig.json[11-14]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@qodo-code-review

Copy link
Copy Markdown

Qodo Fixer

🍒 Ready to be cherry-picked — ✅ Merged (0) · ☑ Fixed (7)

Grey Divider

🔗 Fix PR: #19

This fix PR was closed automatically. Its branch is preserved so you can cherry pick the changes into the original PR.

Prompt for coding agent

This is an automated fix prepared on a separate branch (#19). It is NOT applied to this PR.
To use it: review Fix PR #19 (https://github.com/wave-av/cli/pull/19), evaluate each change critically against your local context, and cherry-pick the changes that are correct into this branch. Do not accept them blindly.
Process — 7 fixed
  • ☑ Fixed: Login leaves project unusable
  • ☑ Fixed: API key sent off-host
  • ☑ Fixed: lint script missing eslint
  • ☑ Fixed: Templates depend on non-existent @wave/sdk package
  • ☑ Fixed: Recovered auth/config code imports missing types module
  • ☑ Fixed: Bundled init misses templates
  • ☑ Fixed: Clean SSE EOF hangs

@yakimoto
yakimoto enabled auto-merge August 5, 2026 02:20
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