Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions clients/agent-runtime/CONTRIBUTING.md
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ When PR traffic is high (especially with AI-assisted contributions), these rules
- **Explicit rollback**: every PR must include a fast rollback path.
- **Security-first review**: changes in `src/security/`, runtime, and CI need stricter validation.

Full maintainer workflow: see [`../web/apps/docs/src/content/docs/en/clients/agent-runtime/pr-workflow.md`](../web/apps/docs/src/content/docs/en/clients/agent-runtime/pr-workflow.md).
CI workflow ownership and triage map: see [`../web/apps/docs/src/content/docs/en/clients/agent-runtime/ci-map.md`](../web/apps/docs/src/content/docs/en/clients/agent-runtime/ci-map.md).
Full maintainer workflow: see [`../web/apps/docs/src/content/docs/clients/agent-runtime/pr-workflow.md`](../web/apps/docs/src/content/docs/clients/agent-runtime/pr-workflow.md).
CI workflow ownership and triage map: see [`../web/apps/docs/src/content/docs/clients/agent-runtime/ci-map.md`](../web/apps/docs/src/content/docs/clients/agent-runtime/ci-map.md).

## Agent Collaboration Guidance

Expand Down
2 changes: 1 addition & 1 deletion clients/agent-runtime/firmware/corvus-esp32-ui/README.md
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,4 @@ MIT - See root `LICENSE`

- [Slint ESP32 Documentation](https://slint.dev/esp32)
- [ESP-IDF Rust Book](https://docs.espressif.com/projects/rust/book/)
- [Corvus Hardware Design](../../../web/apps/docs/src/content/docs/en/guides/hardware-peripherals-design.md)
- [Corvus Hardware Design](../../../web/apps/docs/src/content/docs/guides/hardware-peripherals-design.md)
18 changes: 14 additions & 4 deletions clients/web/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,29 @@ clients/web/
### docs

- Framework: Astro + Starlight
- Default port: 4321
- Portless dev URL: `http://docs.localhost:1355`
- Legacy dev port (PORTLESS=0): 4321

### marketing

- Framework: Astro
- URL configurable with `MARKETING_URL` (dev default: `http://localhost:9988`)
- Portless dev URL: `http://marketing.localhost:1355`
- Legacy dev port (PORTLESS=0): 9988
- URL configurable with `MARKETING_URL` (dev fallback: `http://localhost:9988`)
- Includes public install script at `/install`

### chat

- Framework: Vue 3 + Vite + Tailwind + shadcn-vue style components
- Default port: 4323
- Portless dev URL: `http://chat.localhost:1355`
- Legacy dev port (PORTLESS=0): 4323
- ChatGPT-style conversational interface

### dashboard

- Framework: Vue 3 + Vite
- Default port: 4324
- Portless dev URL: `http://dashboard.localhost:1355`
- Legacy dev port (PORTLESS=0): 4324
- Secure admin panel for `GET/PUT /web/admin/config`
- `GET/PUT /web/admin/config` require auth when pairing is enabled (`[gateway] require_pairing = true` in `clients/agent-runtime/config.toml`)
- Supported mechanism: bearer token (`Authorization: Bearer <token>`)
Expand All @@ -53,6 +58,8 @@ Minimum requirements:

- Node.js 22.0.0+
- pnpm 10.30+
- portless (local devDependency; installed via `pnpm install`)
- One-off usage without install: `pnpm dlx portless` or `npx portless`

```bash
# Install workspace dependencies
Expand All @@ -76,6 +83,9 @@ pnpm dev:marketing
pnpm dev:chat
pnpm dev:dashboard

# Run without portless (uses legacy localhost ports)
PORTLESS=0 pnpm dev:chat

# Compatibility (legacy alias)
pnpm dev:landing

Expand Down
4 changes: 3 additions & 1 deletion clients/web/apps/chat/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ pnpm install
pnpm dev:chat
```

Chat runs on <http://localhost:4323>.
Chat runs on <http://chat.localhost:1355> via portless.

Use `PORTLESS=0 pnpm dev:chat` to run on <http://localhost:4323>.
5 changes: 3 additions & 2 deletions clients/web/apps/chat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
"node": ">=22.0.0"
},
"scripts": {
"dev": "vite --config vite.config.ts --port 4323",
"dev": "portless run --name chat vite --config vite.config.ts",
"build": "vue-tsc -b && vite build --config vite.config.ts",
"preview": "vite preview --config vite.config.ts --port 4323",
"preview": "portless run --name chat vite preview --config vite.config.ts",
Comment on lines +11 to +13
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.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if vite.config.ts specifies port 4323 for fallback behavior
fd -t f 'vite.config.ts' clients/web/apps/chat --exec cat {}

Repository: dallay/corvus

Length of output: 674


🏁 Script executed:

fd -t f -i 'readme*' clients/web/apps/chat

Repository: dallay/corvus

Length of output: 88


🏁 Script executed:

git ls-files clients/web/apps/chat | grep -i readme

Repository: dallay/corvus

Length of output: 88


🌐 Web query:

portless PORTLESS=0 environment variable fallback behavior vite

💡 Result:

portless has a built-in “escape hatch” env var:

  • If PORTLESS=0 (or PORTLESS=skip), portless bypasses the proxy entirely and just runs your command normally (no named .localhost URL, no proxy auto-start, and no portless port/host injection). [1]
  • Normally, portless assigns your app a random port (4000–4999) and sets PORT/HOST; because Vite ignores PORT, portless instead auto-injects --port and --host when it is enabled. [1]
  • With PORTLESS=0, that injection doesn’t happen, so Vite falls back to its normal behavior (default dev port, and if that port is taken it will try the next available port). [2]

Example

PORTLESS=0 pnpm dev   # runs plain `vite` (or whatever your dev script runs), no proxy

Sources: portless configuration docs [1]; Vite server option docs (port fallback) [2].


🏁 Script executed:

cat -n clients/web/apps/chat/README.md

Repository: dallay/corvus

Length of output: 956


Fix port fallback for PORTLESS=0 legacy mode.

The --port 4323 flag was removed from the vite commands, and vite.config.ts does not specify server.port. When PORTLESS=0 is set, portless bypasses entirely and Vite falls back to port 5173 instead of the documented 4323.

Add server: { port: 4323 } to vite.config.ts to preserve the README contract: "Use PORTLESS=0 pnpm dev:chat to run on http://localhost:4323".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/web/apps/chat/package.json` around lines 11 - 13, Add an explicit
default port to Vite’s configuration so legacy PORTLESS=0 falls back to 4323:
update vite.config.ts (the export default defineConfig(...) object) to include
server: { port: 4323 } so Vite uses port 4323 when no --port flag is provided;
ensure the property is a numeric value and placed at the top-level of the
exported config object so existing scripts (dev/build/preview) keep their
behavior while preserving the README contract.

"format": "biome format --write src package.json components.json tsconfig*.json vite.config.ts index.html",
"check": "biome check src package.json components.json tsconfig*.json vite.config.ts index.html",
"test": "vitest --config vite.config.ts --run",
Expand All @@ -37,6 +37,7 @@
"@vue/tsconfig": "catalog:",
"happy-dom": "catalog:",
"postcss": "catalog:",
"portless": "catalog:",
"tailwindcss": "catalog:",
"typescript": "catalog:",
"vite": "catalog:",
Expand Down
4 changes: 3 additions & 1 deletion clients/web/apps/dashboard/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ pnpm install
pnpm dev:dashboard
```

Dashboard corre en <http://localhost:4324>.
Dashboard corre en <http://dashboard.localhost:1355> vía portless.

Usa `PORTLESS=0 pnpm dev:dashboard` para correr en <http://localhost:4324>.

## Docker (local-first)

Expand Down
5 changes: 3 additions & 2 deletions clients/web/apps/dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
"node": ">=22.0.0"
},
"scripts": {
"dev": "vite --port 4324",
"dev": "portless run --name dashboard vite",
"build": "vue-tsc -b && vite build",
"preview": "vite preview --port 4324",
"preview": "portless run --name dashboard vite preview",
Comment on lines +11 to +13
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.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

fd -t f "vite.config" clients/web/apps/dashboard/

Repository: dallay/corvus

Length of output: 140


🏁 Script executed:

cat -n clients/web/apps/dashboard/playwright.config.ts

Repository: dallay/corvus

Length of output: 684


🏁 Script executed:

cat -n clients/web/apps/dashboard/vite.config.ts

Repository: dallay/corvus

Length of output: 686


🏁 Script executed:

fd -t f "build.gradle.kts" | head -5

Repository: dallay/corvus

Length of output: 232


🏁 Script executed:

rg -A 5 "portless" clients/web/apps/dashboard/package.json

Repository: dallay/corvus

Length of output: 792


🏁 Script executed:

rg -i "portless" clients/web/ --type-list

Repository: dallay/corvus

Length of output: 446


🏁 Script executed:

fd -t f "portless.config\|portless\." clients/web/

Repository: dallay/corvus

Length of output: 39


🌐 Web query:

portless node port forwarding vite --port flag

💡 Result:

  • Vite supports --port (and --host) on the CLI:

    • vite --port 5173 --host 0.0.0.0
    • or via npm scripts: npm run dev -- --port 5173 --host 0.0.0.0 [1]
  • Portless + Vite: Portless is designed to run your dev server on an assigned port and proxy it to a stable name (e.g. http://myapp.localhost:1355). For frameworks that ignore PORT (including Vite), Portless auto-injects the right --port and --host flags. So this is usually enough:

    • portless myapp npm run dev [2]
  • If you need to pass flags through Portless to Vite, use -- to stop Portless flag parsing and pass the rest to the child command:

    • portless myapp -- npm run dev -- --port 5173 --host 0.0.0.0 [2]
  • If you want Portless to use a fixed internal app port (instead of an auto-assigned one):

    • portless myapp --app-port 5173 npm run dev [2]
  • If you hit a proxy “Bad Gateway” with Vite, ensure Vite is listening on the injected port and on all interfaces (example config shown here): set server.port from process.env.PORT and server.host to 0.0.0.0. [3]

Sources: Vite CLI options [1]; Portless flags/behavior (including Vite auto-injection and -- passthrough) [2]; Vite-specific Portless config notes [3].


🏁 Script executed:

# Check if portless is documented in any README or config files
rg -l "portless" clients/web/ | head -10

Repository: dallay/corvus

Length of output: 417


Fix the Playwright webServer command to work with portless.

Line 11 now routes pnpm dev through portless, but playwright.config.ts line 11 still passes --port 4324 to that script. Portless auto-assigns a dynamic port and ignores downstream --port flags unless passed after -- or configured with --app-port. Playwright will then wait on http://127.0.0.1:4324 while Vite runs on a different port, causing test:e2e to hang or fail.

Either update the Playwright command to:

  • portless run --name dashboard -- vite --host 127.0.0.1 --port 4324, or
  • portless run --name dashboard --app-port 4324 vite --host 127.0.0.1

Or configure Vite to respect PORT env var and let Portless inject it dynamically.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/web/apps/dashboard/package.json` around lines 11 - 13, Playwright is
launching the dev server with a fixed --port but the dev script "dev": "portless
run --name dashboard vite" lets Portless pick a dynamic port and ignores
downstream --port flags; update the Playwright webServer launch command (the
entry that currently invokes the "dev" script) to call portless with either an
explicit passthrough or app-port so Vite sees the port—e.g. change the command
to use "portless run --name dashboard -- vite --host 127.0.0.1 --port 4324" or
"portless run --name dashboard --app-port 4324 vite --host 127.0.0.1"
(alternatively, make Vite respect PORT env and let Portless inject it). Ensure
the change targets the Playwright webServer launch configuration referenced in
playwright.config.ts.

"format": "biome format --write src package.json components.json tsconfig*.json vite.config.ts index.html",
"check": "biome check src package.json components.json tsconfig*.json vite.config.ts index.html",
"test": "vitest --run --environment happy-dom --exclude e2e/**",
Expand Down Expand Up @@ -38,6 +38,7 @@
"@vue/tsconfig": "catalog:",
"happy-dom": "catalog:",
"postcss": "catalog:",
"portless": "catalog:",
"tailwindcss": "catalog:",
"typescript": "catalog:",
"vite": "catalog:",
Expand Down
6 changes: 6 additions & 0 deletions clients/web/apps/docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ pnpm install
# Start dev server
pnpm run dev

# Portless URL (default)
# http://docs.localhost:1355

# Run without portless (legacy localhost port)
PORTLESS=0 pnpm run dev
Comment on lines +20 to +21
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.

⚠️ Potential issue | 🟡 Minor

Document the legacy URL as well.

PORTLESS=0 pnpm run dev is useful, but this section never says that the fallback server is then on http://localhost:4321. Without the URL, the legacy workflow is only half documented.

Suggested doc fix
 # Run without portless (legacy localhost port)
+# http://localhost:4321
 PORTLESS=0 pnpm run dev

As per coding guidelines, "**/*.{md,mdx}: Verify technical accuracy and that docs stay aligned with code changes. For user-facing docs, check EN/ES parity or explicitly note pending translation gaps."

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Run without portless (legacy localhost port)
PORTLESS=0 pnpm run dev
# Run without portless (legacy localhost port)
# http://localhost:4321
PORTLESS=0 pnpm run dev
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/web/apps/docs/README.md` around lines 20 - 21, Update the docs line
that shows the legacy startup command so it also documents the fallback server
URL; specifically, modify the README entry for "PORTLESS=0 pnpm run dev" to
state that the legacy server will be available at http://localhost:4321 (or the
configured port), ensuring the command text "PORTLESS=0 pnpm run dev" and the
URL are included together so readers know where to access the running app.


# Build static site
pnpm run build

Expand Down
15 changes: 11 additions & 4 deletions clients/web/apps/docs/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ const DEFAULT_PROD_URL = "https://docs.profiletailors.com";

const mode = process.env.NODE_ENV || "production";
const env = loadEnv(mode, process.cwd(), "");
const portlessUrl =
mode === "production" ? undefined : process.env.PORTLESS_URL ?? env.PORTLESS_URL;
const runtimeEnv = portlessUrl ? { ...env, DOCS_URL: portlessUrl } : env;
const docsUrl = resolveSiteUrl({
env,
env: runtimeEnv,
primaryKey: "DOCS_URL",
localDefault: DEFAULT_DEV_URL,
productionDefault: DEFAULT_PROD_URL,
Expand All @@ -22,7 +25,11 @@ const docsUrl = resolveSiteUrl({
},
isProdLike: mode === "production",
});
const resolvedPort = getPortFromUrl(docsUrl, PORTS.DOCS);
const portCandidate = process.env.PORT ?? env.PORT;
const parsedPort = Number.parseInt(portCandidate ?? "", 10);
const resolvedPort = Number.isFinite(parsedPort)
? parsedPort
: getPortFromUrl(docsUrl, PORTS.DOCS);

export default defineConfig({
site: docsUrl,
Expand All @@ -42,9 +49,9 @@ export default defineConfig({
light: "./public/favicon.svg",
dark: "./public/favicon-light.svg",
},
defaultLocale: "en",
defaultLocale: "root",
locales: {
en: { label: "English", lang: "en" },
root: { label: "English", lang: "en" },
es: { label: "Español", lang: "es" },
},
plugins: [viewTransitions()],
Expand Down
7 changes: 4 additions & 3 deletions clients/web/apps/docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
"type": "module",
"version": "0.4.0",
"scripts": {
"dev": "astro dev",
"start": "astro dev",
"dev": "portless run --name docs astro dev",
"start": "portless run --name docs astro dev",
"build": "astro build",
"preview": "astro preview",
"preview": "portless run --name docs astro preview",
"astro": "astro",
"format": "biome format --write src astro.config.mjs package.json tsconfig.json",
"lint": "biome lint src astro.config.mjs",
Expand All @@ -21,6 +21,7 @@
"devDependencies": {
"@astrojs/check": "catalog:",
"astro-vtbot": "catalog:",
"portless": "catalog:",
"typescript": "catalog:",
"vite": "catalog:"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Contiene todas las aplicaciones cliente que consumen los módulos compartidos:

## El Directorio `docs`

- **`docs/es/`**: Documentación en español.
- **`docs/`**: Documentación en inglés (locale raíz).
- `index.mdx`: Página de inicio.
- `guides/`: Guías detalladas del proyecto.
- **`docs/en/`**: Documentación en inglés (si aplica).
- **`docs/es/`**: Documentación en español.
Comment on lines +48 to +51
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.

⚠️ Potential issue | 🟡 Minor

Fix the Spanish locale paths.

These entries still point to docs/ and docs/es/, but the actual paths after this locale swap are under clients/web/apps/docs/src/content/docs/. Right now the ES page diverges from the English guide and sends readers to directories that do not exist at the repo root.

Suggested doc fix
-- **`docs/`**: Documentación en inglés (locale raíz).
+- **`clients/web/apps/docs/src/content/docs/`**: Documentación en inglés (locale raíz).
   - `index.mdx`: Página de inicio.
   - `guides/`: Guías detalladas del proyecto.
-- **`docs/es/`**: Documentación en español.
+- **`clients/web/apps/docs/src/content/docs/es/`**: Documentación en español.

As per coding guidelines, "**/*.{md,mdx}: Verify technical accuracy and that docs stay aligned with code changes. For user-facing docs, check EN/ES parity or explicitly note pending translation gaps."

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- **`docs/`**: Documentación en inglés (locale raíz).
- `index.mdx`: Página de inicio.
- `guides/`: Guías detalladas del proyecto.
- **`docs/en/`**: Documentación en inglés (si aplica).
- **`docs/es/`**: Documentación en español.
- **`clients/web/apps/docs/src/content/docs/`**: Documentación en inglés (locale raíz).
- `index.mdx`: Página de inicio.
- `guides/`: Guías detalladas del proyecto.
- **`clients/web/apps/docs/src/content/docs/es/`**: Documentación en español.
🧰 Tools
🪛 LanguageTool

[grammar] ~49-~49: Elimina la puntuación
Context: ...en inglés (locale raíz). - index.mdx: Página de inicio. - guides/: Guías ...

(QB_NEW_ES_OTHER_ERROR_IDS_UNNECESSARY_PUNCTUATION)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/web/apps/docs/src/content/docs/es/guides/structure.md` around lines
48 - 51, The Spanish locale section currently references top-level paths `docs/`
and `docs/es/` that no longer exist; update the ES entries so they mirror the
English entries using the project's docs content root (i.e., use the same
relative paths for `index.mdx` and `guides/` under the project's docs content
directory rather than `docs/`/`docs/es/`) so the Spanish guide points to the
correct in-repo locations and stays aligned with the English version.

Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Contains all client applications that consume the shared modules:

## Documentation

- **`clients/web/apps/docs/src/content/docs/es/`**: Documentation in Spanish.
- **`clients/web/apps/docs/src/content/docs/`**: Documentation in English (root locale).
- `index.mdx`: Home page.
- `guides/`: Detailed project guides.
- **`clients/web/apps/docs/src/content/docs/en/`**: Documentation in English.
- **`clients/web/apps/docs/src/content/docs/es/`**: Documentation in Spanish.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ description: Welcome to the Corvus Agent Platform documentation.

**Corvus** is a highly extensible, multi-interface agentic platform designed to bridge the gap between AI autonomy and human supervision. Built with a robust **Kotlin Multiplatform** foundation and powered by a high-performance **Rust** runtime, Corvus provides a secure, sandboxed environment for AI agents to perform complex, multi-step tasks.

![Corvus Architecture](../../../../assets/corvus.png)
![Corvus Architecture](../../../assets/corvus.png)

## ✨ Features

Expand Down
7 changes: 7 additions & 0 deletions clients/web/apps/docs/src/pages/en/[...slug].astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
const { slug } = Astro.params;
const baseUrl = import.meta.env.BASE_URL.endsWith("/")
? import.meta.env.BASE_URL.slice(0, -1)
: import.meta.env.BASE_URL;
Astro.redirect(`${baseUrl}${slug ? `/${slug}` : "/"}`);
Comment on lines +2 to +6
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.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In Astro v5, does page frontmatter need return Astro.redirect(...) for the redirect response to be sent?

💡 Result:

Yes. In Astro v5, a page must return Astro.redirect(...) from its frontmatter for the redirect response to be sent; just calling Astro.redirect(...) without returning it will not trigger the redirect. [1]

(And Astro.redirect() returns a Response, which is one of the only valid things you can return from a page.) [2]

Sources: [1] Astro API reference (redirect()), [2] Astro error docs (“Only Response can be returned”)


Return the redirect response.

This calls Astro.redirect(...) but never returns it, leaving legacy /en/* requests to render as pages instead of triggering redirects.

Minimal fix
-Astro.redirect(`${baseUrl}${slug ? `/${slug}` : "/"}`);
+return Astro.redirect(`${baseUrl}${slug ? `/${slug}` : "/"}`);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/web/apps/docs/src/pages/en/`[...slug].astro around lines 2 - 6,
Astro.redirect(...) is being invoked but its response is not returned, so
requests under /en/* continue to render; update the handler to return the
redirect response by returning the result of Astro.redirect(...) (use the
existing symbols: Astro.redirect, slug, baseUrl) so the redirect is actually
sent to the client.

---
8 changes: 0 additions & 8 deletions clients/web/apps/docs/src/pages/index.astro

This file was deleted.

8 changes: 6 additions & 2 deletions clients/web/apps/marketing/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,15 @@ pnpm build:marketing
pnpm --filter @corvus/marketing run check
```

Dev URL (portless): <http://marketing.localhost:1355>

Sin portless: `PORTLESS=0 pnpm dev:marketing` (usa `http://localhost:9988`).

## Configuración de dominio y puerto

- Dev default: `http://localhost:9988`
- Dev default: `http://marketing.localhost:1355` (portless)
- Prod default: `https://profiletailors.com`
- El puerto de `dev/preview` se toma de `MARKETING_URL` si incluye puerto; si no, usa `9988`
- El puerto de `dev/preview` se toma de `PORT` (portless) o de `MARKETING_URL` si incluye puerto; si no, usa `9988`

Variable soportada:

Expand Down
12 changes: 10 additions & 2 deletions clients/web/apps/marketing/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,19 @@ const DEFAULT_PROD_URL = "https://profiletailors.com";
const mode = process.env.NODE_ENV || "production";
const env = loadEnv(mode, process.cwd(), "");

const portlessUrl =
mode === "production"
? ""
: resolvePublicUrl(process.env.PORTLESS_URL ?? env.PORTLESS_URL, "");
const marketingUrl = resolvePublicUrl(
env.MARKETING_URL,
env.MARKETING_URL ?? (portlessUrl || undefined),
mode === "production" ? DEFAULT_PROD_URL : DEFAULT_DEV_URL
);
const resolvedPort = getPortFromUrl(marketingUrl, PORTS.MARKETING);
const portCandidate = process.env.PORT ?? env.PORT;
const parsedPort = Number.parseInt(portCandidate ?? "", 10);
const resolvedPort = Number.isFinite(parsedPort)
? parsedPort
: getPortFromUrl(marketingUrl, PORTS.MARKETING);
Comment on lines +20 to +24
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.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, examine the actual file
cat -n clients/web/apps/marketing/astro.config.mjs | head -40

Repository: dallay/corvus

Length of output: 1530


🏁 Script executed:

# Test Number.parseInt() behavior with the claimed problematic values
node <<'EOF'
console.log("Testing Number.parseInt() behavior:");
console.log("parseInt('123abc', 10):", Number.parseInt("123abc", 10));
console.log("parseInt('0', 10):", Number.parseInt("0", 10));
console.log("parseInt('70000', 10):", Number.parseInt("70000", 10));
console.log("parseInt('', 10):", Number.parseInt("", 10));
console.log("parseInt('abc', 10):", Number.parseInt("abc", 10));
console.log("");
console.log("isFinite() checks:");
console.log("isFinite(123):", Number.isFinite(123));
console.log("isFinite(NaN):", Number.isFinite(NaN));
console.log("isFinite(0):", Number.isFinite(0));
console.log("isFinite(70000):", Number.isFinite(70000));
console.log("");
console.log("isInteger() checks:");
console.log("isInteger(123):", Number.isInteger(123));
console.log("isInteger(0):", Number.isInteger(0));
console.log("isInteger(NaN):", Number.isInteger(NaN));
console.log("");
console.log("Port range validation [1..65535]:");
console.log("Valid port 80:", 80 >= 1 && 80 <= 65535);
console.log("Valid port 8080:", 8080 >= 1 && 8080 <= 65535);
console.log("Invalid port 0:", 0 >= 1 && 0 <= 65535);
console.log("Invalid port 65536:", 65536 >= 1 && 65536 <= 65535);
console.log("Invalid port 70000:", 70000 >= 1 && 70000 <= 65535);
EOF

Repository: dallay/corvus

Length of output: 552


🏁 Script executed:

# Test the regex pattern from the diff suggestion
node <<'EOF'
const regex = /^(?:0|[1-9]\d{0,4})$/;
const testValues = ["0", "1", "80", "8080", "65535", "65536", "70000", "123abc", "abc", "", "00", "08", "99999"];
console.log("Testing regex /^(?:0|[1-9]\\d{0,4})$/:");
testValues.forEach(val => {
  console.log(`"${val}": ${regex.test(val)}`);
});
EOF

Repository: dallay/corvus

Length of output: 257


Fix port validation—current regex in diff allows invalid ports beyond 65535.

The issue is real: Number.parseInt() accepts partial strings ("123abc"123) and out-of-range values, bypassing fallback logic. However, the suggested regex /^(?:0|[1-9]\d{0,4})$/ still accepts invalid ports like 65536, 70000, and 99999 because [1-9]\d{0,4} allows up to 5 digits.

Use a strict range check instead:

Corrected diff
 const portCandidate = process.env.PORT ?? env.PORT;
-const parsedPort = Number.parseInt(portCandidate ?? "", 10);
-const resolvedPort = Number.isFinite(parsedPort)
+const parsedPort = Number.parseInt(portCandidate ?? "", 10);
+const resolvedPort =
+  Number.isInteger(parsedPort) && parsedPort >= 1 && parsedPort <= 65535
   ? parsedPort
   : getPortFromUrl(marketingUrl, PORTS.MARKETING);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@clients/web/apps/marketing/astro.config.mjs` around lines 20 - 24, The port
parsing currently uses Number.parseInt on portCandidate which accepts partial
strings and out-of-range values; update the logic around
portCandidate/parsedPort/resolvedPort to first ensure portCandidate is purely
digits (e.g., match /^\d+$/) then parse to an integer and validate it's between
0 and 65535 (inclusive); if the digit check or range check fails, fall back to
getPortFromUrl(marketingUrl, PORTS.MARKETING); keep references to portCandidate,
parsedPort, resolvedPort, getPortFromUrl, and PORTS.MARKETING so reviewers can
find and verify the change.


export default defineConfig({
site: marketingUrl,
Expand Down
7 changes: 4 additions & 3 deletions clients/web/apps/marketing/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
"type": "module",
"scripts": {
"copy-install": "bash -c 'if [ -f ../../../../scripts/install.sh ]; then cp ../../../../scripts/install.sh public/install; else echo \"scripts/install.sh not found; skipping copy\"; fi'",
"dev": "astro dev",
"dev": "portless run --name marketing astro dev",
"predev": "pnpm run copy-install",
"start": "astro dev",
"start": "portless run --name marketing astro dev",
"build": "astro build",
"prebuild": "pnpm run copy-install",
"preview": "astro preview",
"preview": "portless run --name marketing astro preview",
"astro": "astro",
"format": "biome format --write src public package.json astro.config.mjs tsconfig.json README.md",
"check": "biome check src public package.json astro.config.mjs tsconfig.json README.md",
Expand All @@ -23,6 +23,7 @@
"sharp": "catalog:"
},
"devDependencies": {
"portless": "catalog:",
"typescript": "catalog:",
"vite": "catalog:"
}
Expand Down
Loading
Loading