Skip to content

feat(cli): fetch AI summaries and video info from share links (#2015) - #2089

Open
Samarth1306w wants to merge 5 commits into
CapSoftware:mainfrom
Samarth1306w:feature/cli-fetch-ai-summaries-from-share-links-2015
Open

feat(cli): fetch AI summaries and video info from share links (#2015)#2089
Samarth1306w wants to merge 5 commits into
CapSoftware:mainfrom
Samarth1306w:feature/cli-fetch-ai-summaries-from-share-links-2015

Conversation

@Samarth1306w

@Samarth1306w Samarth1306w commented Aug 6, 2026

Copy link
Copy Markdown

Fixes #2015

Summary

  1. API Endpoint (): Added endpoint returning title, AI summary, chapters, and for public videos or owner-authenticated requests.
  2. CLI Command (): Added subcommand accepting share URLs or video IDs (respecting for self-hosted instances) to print summary/chapters or output JSON ().

Greptile Summary

Adds a CLI command and web endpoint for retrieving video titles, AI summaries, chapters, and generation status, alongside rate limiting and teleprompter behavior adjustments.

  • Adds cap recordings info with text and JSON output.
  • Adds a public/owner-gated video metadata GET endpoint.
  • Rate-limits analytics tracking and guest checkout requests.
  • Preserves desktop and mobile teleprompter progress across relayouts.

Confidence Score: 3/5

The PR should not merge until the metadata endpoint enforces password-aware video access, because it currently discloses protected summaries and chapters.

The new endpoint independently authorizes public videos without the canonical password checks, allowing unauthenticated metadata disclosure; the CLI URL parsing and metadata typing issues are additional non-blocking concerns.

Files Needing Attention: apps/web/app/api/video/metadata/route.ts, apps/cli/src/recordings.rs

Important Files Changed

Filename Overview
apps/web/app/api/video/metadata/route.ts Adds metadata retrieval but bypasses password-aware viewing policy and introduces an explicit any cast.
apps/cli/src/recordings.rs Implements metadata fetching and output, but raw share-link splitting mishandles URLs containing query parameters.
apps/cli/src/main.rs Wires the asynchronous recordings info subcommand into the existing command and output-format dispatch.
apps/web/app/api/analytics/track/route.ts Adds an early rate-limit response before analytics request processing.
apps/web/app/api/settings/billing/guest-checkout/route.ts Adds an early rate-limit response before creating guest checkout sessions.
apps/desktop/src/routes/teleprompter.tsx Preserves the current scroll offset while resizing the teleprompter editor.
apps/mobile/src/recording/TeleprompterOverlay.tsx Stops resetting playback progress after the initial text layout.
apps/web/tests/unit/rate-limit-ids.test.ts Adds a source-reference contract test for active rate-limit identifiers.
Prompt To Fix All With AI
### Issue 1
apps/web/app/api/video/metadata/route.ts:60-62
**Password-aware access is bypassed**

When an unauthenticated caller requests a public video protected by a direct or inherited space password, this check treats `video.public` as sufficient authorization and returns its title, AI summary, and chapters without the required password. **How this was verified:** The endpoint's direct public check was compared with the canonical viewing policy, which verifies password candidates for public videos.

### Issue 2
apps/cli/src/recordings.rs:111-119
**Share URL queries enter IDs**

For a share URL containing a query string, `rsplit('/')` includes that query in `video_id`, so the metadata endpoint looks up a value such as `abc123?utm_source=...` instead of `abc123`. Parse the URL and extract its final path segment, as the existing CLI target parser does.

### Issue 3
apps/web/app/api/video/metadata/route.ts:65
**Metadata bypasses type narrowing**

Casting metadata to `Record<string, any>` removes type checking from the new API boundary, preventing incompatible summary, chapter, or generation-status shapes from being detected. Use `unknown` with narrowing or an existing shared metadata type, as required by the repository's TypeScript guidance.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "feat(cli): fetch AI summaries and video ..." | Re-trigger Greptile

Greptile also left 3 inline comments on this PR.

Context used (5)

@superagent-security

Copy link
Copy Markdown

🚨 Contributor flagged. Click here for more info: Superagent Dashboard

return Response.json(true, { status: 200 });
}

export async function GET(request: NextRequest) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: New video metadata endpoint lacks rate limiting

Public GET endpoint queries the database without throttling, enabling potential enumeration or DoS.

Add isRateLimited() with an appropriate RATE_LIMIT_IDS entry, matching the pattern in nearby endpoints.

AI prompt
Check if this security scanner issue is valid. If so, understand the root cause and fix it. If appropriate, update or add tests. Keep the change focused and preserve intended behavior.

<file name="apps/web/app/api/video/metadata/route.ts">
<violation number="1" location="apps/web/app/api/video/metadata/route.ts:43">
<priority>P2</priority>
<title>New video metadata endpoint lacks rate limiting</title>
<evidence>The new GET handler in apps/web/app/api/video/metadata/route.ts is publicly accessible for public videos and performs a database query on every request, but it does not apply any rate limiting. The same PR adds isRateLimited() calls to the analytics track and guest-checkout endpoints, indicating awareness of the need for rate limiting.</evidence>
<recommendation>Add rate limiting at the start of the GET handler using isRateLimited() and RATE_LIMIT_IDS, following the same pattern as the analytics/track and billing/guest-checkout endpoints in this PR.</recommendation>
</violation>
</file>

Comment on lines +60 to +62
if (!video.public && video.ownerId !== user?.id) {
return Response.json({ error: "Unauthorized" }, { status: 401 });
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 security Password-aware access is bypassed

When an unauthenticated caller requests a public video protected by a direct or inherited space password, this check treats video.public as sufficient authorization and returns its title, AI summary, and chapters without the required password. How this was verified: The endpoint's direct public check was compared with the canonical viewing policy, which verifies password candidates for public videos.

Knowledge Base Used: Web App (apps/web)

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/web/app/api/video/metadata/route.ts
Line: 60-62

Comment:
**Password-aware access is bypassed**

When an unauthenticated caller requests a public video protected by a direct or inherited space password, this check treats `video.public` as sufficient authorization and returns its title, AI summary, and chapters without the required password. **How this was verified:** The endpoint's direct public check was compared with the canonical viewing policy, which verifies password candidates for public videos.

**Knowledge Base Used:** [Web App (apps/web)](https://app.greptile.com/cap/-/custom-context/knowledge-base/capsoftware/cap/-/docs/web-app.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Comment on lines +111 to +119
let video_id = if url_or_id.contains('/') {
url_or_id
.rsplit('/')
.next()
.unwrap_or(&url_or_id)
.to_string()
} else {
url_or_id
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Share URL queries enter IDs

For a share URL containing a query string, rsplit('/') includes that query in video_id, so the metadata endpoint looks up a value such as abc123?utm_source=... instead of abc123. Parse the URL and extract its final path segment, as the existing CLI target parser does.

Knowledge Base Used: Cap CLI (apps/cli)

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/cli/src/recordings.rs
Line: 111-119

Comment:
**Share URL queries enter IDs**

For a share URL containing a query string, `rsplit('/')` includes that query in `video_id`, so the metadata endpoint looks up a value such as `abc123?utm_source=...` instead of `abc123`. Parse the URL and extract its final path segment, as the existing CLI target parser does.

**Knowledge Base Used:** [Cap CLI (`apps/cli`)](https://app.greptile.com/cap/-/custom-context/knowledge-base/capsoftware/cap/-/docs/cli.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

}

const meta = (video.metadata as Record<string, any>) ?? {};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Metadata bypasses type narrowing

Casting metadata to Record<string, any> removes type checking from the new API boundary, preventing incompatible summary, chapter, or generation-status shapes from being detected. Use unknown with narrowing or an existing shared metadata type, as required by the repository's TypeScript guidance.

Context Used: AGENTS.md (source)

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/web/app/api/video/metadata/route.ts
Line: 65

Comment:
**Metadata bypasses type narrowing**

Casting metadata to `Record<string, any>` removes type checking from the new API boundary, preventing incompatible summary, chapter, or generation-status shapes from being detected. Use `unknown` with narrowing or an existing shared metadata type, as required by the repository's TypeScript guidance.

**Context Used:** AGENTS.md ([source](https://github.com/capsoftware/cap/blob/main/AGENTS.md))

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

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.

CLI: fetch AI summaries from share links

2 participants