Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix(http): raw request bytes for webhook signature verification + blueprint stripe webhook - #244

Merged
RohinBhargava merged 4 commits into
mainfrom
rohin/raw-body-webhooks
Aug 11, 2026
Merged

fix(http): raw request bytes for webhook signature verification + blueprint stripe webhook#244
RohinBhargava merged 4 commits into
mainfrom
rohin/raw-body-webhooks

Conversation

@RohinBhargava

@RohinBhargava RohinBhargava commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes the reported defect: routes could not receive raw, unparsed request bytes, making Stripe/GitHub/Slack-style HMAC signature verification impossible. All three underlying defects are fixed, published ([email protected], [email protected], [email protected]), and the blueprint's Stripe webhook now uses the fix.

Primary fix — raw bytes via the parser verify hook

  • express contentParse builds every body-parser with a verify that stashes the exact request bytes on req._rawBody; req.body stays the parsed value; user-supplied verify callbacks still run
  • hyper-express captures req._rawBody via req.buffer() before parsing (body is cached and reused by json()/text(); multipart excluded)
  • core parse middleware no longer clobbers a parser-captured _rawBody (??= keeps the pre-validation body as fallback for adapters without capture)

Defect #1 — per-route contentType now applies to the dispatched parser

body: { text: string, contentType: 'application/json' } parses JSON-typed requests as raw text. The override only applies when it differs from the parser's default, preserving default matching semantics.

Defect #2 — application-level parser options reach router parsing

Parsers are now built lazily from req._globalOptions() (the mount-time merge of app+router options) instead of eagerly at construction, so forklaunchExpress(sv, otel, { text: { type: [...] } }) works as a global escape hatch.

HMAC compatibility

createHmacToken signs Buffer/string bodies verbatim, so verification over captured raw bytes matches clients that sign an object and send its stringification — byte-for-byte, and now immune to validation-time property reordering.

Blueprint

  • Stripe webhook declares body: { text: string, contentType: 'application/json' }req.body is the exact payload string stripe.webhooks.constructEvent verifies (previously the route 400'd before the handler ran)
  • Framework deps bumped; also repaired pre-existing typecheck breaks (reproduced on main with prior dep versions): EraseResult/ExportResult spread into res.json literals, and surfacePermissions/surfaceRoles payload annotations where inference collapsed to never

Tests

  • New express/__test__/rawBody.webhook.test.ts (5 tests): parsed body + exact raw bytes (formatting preserved), defect Validator and Core Refactor #1 route shape, defect Package tests and http framework stubs #2 global widening, default content types unbroken, HMAC raw-bytes/object token equality
  • Suites: core 371, express 32 (incl. new), hyper-express 19 (one pre-existing local uWS port flake on a GET test, reproduced on unmodified main; CI is unaffected)
  • Full blueprint workspace builds green against the published packages

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Improved webhook signature verification by preserving exact JSON and text request payloads.
    • Improved compatibility with custom content types and request parsing.
    • Standardized successful GDPR export and erasure responses across billing and identity features.
  • Documentation

    • Added guidance for infrastructure management, local development, routing, authentication, migrations, and troubleshooting.
  • Chores

    • Updated framework and blueprint components to compatible runtime versions.
    • Added coverage for raw webhook payload handling and HMAC signing.

RohinBhargava and others added 2 commits August 10, 2026 23:53
Routes could not receive the raw, unparsed request bytes, making
HMAC/webhook signature verification (Stripe, GitHub, Slack, ...)
impossible without bypassing the framework entirely.

- express contentParse builds every body-parser with a verify hook that
  stashes the exact request bytes on req._rawBody, while req.body stays
  the parsed value; user-supplied verify callbacks still run
- per-route contentType now applies to the dispatched parser (a body
  declared as text with contentType application/json parses JSON-typed
  requests as raw text) — overrides only when it differs from the
  parser's default so default matching semantics are preserved
- parser options are resolved lazily from req._globalOptions(), so
  application-level json/text/raw/urlencoded/busboy options reach
  router-level parsing (previously parsers were built at construction
  time, before addRouterOptions merged app options into routers)
- hyper-express captures req._rawBody via req.buffer() before parsing
  (multipart excluded); the cached body is reused by json()/text()
- core parse middleware no longer clobbers a parser-captured _rawBody
  (now _rawBody ??= body), and createHmacToken signs Buffer/string
  bodies verbatim so raw-bytes verification matches object-signing
  clients byte-for-byte

Published as @forklaunch/[email protected], @forklaunch/[email protected],
@forklaunch/[email protected].

Co-Authored-By: Claude Fable 5 <[email protected]>
- webhook route declares body as text with contentType application/json
  (new framework support), so req.body is the exact payload string that
  stripe.webhooks.constructEvent verifies — previously the text parser
  never matched Stripe's application/json posts and requests failed
  validation before the handler ran
- bump @forklaunch/core to 1.5.11 and express/hyper-express to 1.2.38
- fix pre-existing typecheck breaks surfaced by the dep refresh
  (present on main with prior versions too): spread EraseResult/
  ExportResult into res.json literals (interfaces lack index
  signatures) and annotate surfacePermissions/surfaceRoles payload
  params where inference collapsed to never

Co-Authored-By: Claude Fable 5 <[email protected]>
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR preserves raw webhook payloads during request parsing and HMAC signing. It updates Express and Hyper-Express middleware, webhook schema configuration, compliance responses, IAM callback typing, package versions, and CLI documentation.

Changes

Webhook and compliance integration

Layer / File(s) Summary
Raw-body HMAC handling
framework/core/src/http/createHmacToken.ts, framework/core/src/http/middleware/request/parse.middleware.ts, framework/core/package.json
String and Buffer bodies retain their UTF-8 content during HMAC signing. Existing captured raw bodies remain unchanged during request parsing.
Express and Hyper-Express body parsing
framework/express/src/middleware/*, framework/express/__test__/rawBody.webhook.test.ts, framework/hyper-express/src/middleware/contentParse.middleware.ts, framework/*/package.json
The adapters capture raw bytes before parsing. Express adds lazy parser creation, caching, option resolution, content-type matching, and integration tests.
Blueprint integration and dependency adoption
blueprint/*, blueprint/implementations/*
Compliance endpoints serialize shallow result copies. The Stripe webhook schema declares JSON content with text parsing. IAM callbacks declare optional string sub payloads. Blueprint packages adopt updated runtime versions.
CLI metadata and skill documentation
cli/src/core/package_json/package_json_constants.rs, cli/assets/forklaunch-skills/*
CLI package constants and operational skill documents describe updated package versions, commands, infrastructure operations, framework behavior, and troubleshooting guidance.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Stripe
  participant contentParse
  participant WebhookController
  participant createHmacToken
  Stripe->>contentParse: send signed JSON payload
  contentParse->>contentParse: capture exact raw bytes
  contentParse->>WebhookController: provide parsed body and _rawBody
  WebhookController->>createHmacToken: pass raw payload
  createHmacToken->>WebhookController: construct UTF-8 HMAC payload
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: preserving raw HTTP request bytes for webhook signature verification and updating the Stripe blueprint.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch rohin/raw-body-webhooks

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

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
framework/express/__test__/rawBody.webhook.test.ts (1)

1-5: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use the required test filename and import layers.

Rename this file to rawBodyWebhook.test.ts. Move the http import before package imports.

As per coding guidelines, **/*.test.ts must use camelCase <resource>.test.ts names, and TypeScript imports must place Node built-ins before external dependencies.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@framework/express/__test__/rawBody.webhook.test.ts` around lines 1 - 5,
Rename the test file to rawBodyWebhook.test.ts and reorder its imports so the
Node built-in http import appears before all external package imports, while
preserving the existing forklaunch and validator imports.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@framework/core/src/http/createHmacToken.ts`:
- Around line 35-45: Update the body canonicalization in createHmacToken to keep
Buffer inputs binary-safe by passing the original Buffer bytes to hmac.update
rather than decoding them as UTF-8, while retaining the newline delimiter for
every body type. Preserve existing string and object serialization behavior, and
add a regression test using non-UTF-8 bytes to verify the generated HMAC matches
the raw payload.

In `@framework/express/__test__/rawBody.webhook.test.ts`:
- Around line 10-11: Update the test server setup around PORT and HOST to listen
on port 0 instead of reserving fixed port 6480, then construct the host URL from
the actual address returned by server.address() after the server is listening.
Ensure all webhook requests use this dynamically resolved host.

---

Nitpick comments:
In `@framework/express/__test__/rawBody.webhook.test.ts`:
- Around line 1-5: Rename the test file to rawBodyWebhook.test.ts and reorder
its imports so the Node built-in http import appears before all external package
imports, while preserving the existing forklaunch and validator imports.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0e15928a-91bf-43cf-a661-6a41f13c3813

📥 Commits

Reviewing files that changed from the base of the PR and between e617f96 and e2c1f93.

⛔ Files ignored due to path filters (1)
  • blueprint/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (34)
  • blueprint/billing-base/api/controllers/compliance.controller.ts
  • blueprint/billing-base/package.json
  • blueprint/billing-stripe/api/controllers/compliance.controller.ts
  • blueprint/billing-stripe/api/controllers/webhook.controller.ts
  • blueprint/billing-stripe/package.json
  • blueprint/client-sdk/package.json
  • blueprint/core/package.json
  • blueprint/ecommerce-stripe/package.json
  • blueprint/iam-base/api/controllers/compliance.controller.ts
  • blueprint/iam-base/package.json
  • blueprint/iam-base/server.ts
  • blueprint/iam-better-auth/api/controllers/compliance.controller.ts
  • blueprint/iam-better-auth/package.json
  • blueprint/iam-better-auth/registrations.ts
  • blueprint/implementations/billing/base/package.json
  • blueprint/implementations/billing/stripe/package.json
  • blueprint/implementations/ecommerce/base/package.json
  • blueprint/implementations/iam/base/package.json
  • blueprint/implementations/worker/bullmq/package.json
  • blueprint/implementations/worker/database/package.json
  • blueprint/implementations/worker/kafka/package.json
  • blueprint/implementations/worker/redis/package.json
  • blueprint/monitoring/package.json
  • blueprint/package.json
  • blueprint/pnpm-workspace.yaml
  • blueprint/sample-worker/package.json
  • framework/core/package.json
  • framework/core/src/http/createHmacToken.ts
  • framework/core/src/http/middleware/request/parse.middleware.ts
  • framework/express/__test__/rawBody.webhook.test.ts
  • framework/express/package.json
  • framework/express/src/middleware/content.parse.middleware.ts
  • framework/hyper-express/package.json
  • framework/hyper-express/src/middleware/contentParse.middleware.ts

Comment on lines +35 to 45
const bodyString = body
? `${
Buffer.isBuffer(body)
? body.toString('utf8')
: typeof body === 'string'
? body
: safeStringify(body)
}\n`
: undefined;
hmac.update(
`${method}\n${path}\n${bodyString}${timestamp.toISOString()}\n${nonce}`

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Official Node.js documentation: Does crypto.Hmac.update()accept a Buffer, and how doesBuffer.toString('utf8') process invalid UTF-8 byte sequences?

💡 Result:

Yes, the crypto.Hmac.update() method in Node.js accepts a Buffer [1][2][3]. According to official Node.js documentation, when update() is called, the provided data can be a string, Buffer, TypedArray, or DataView. If the data is a Buffer, TypedArray, or DataView, the inputEncoding argument is ignored [4][1][3]. Regarding Buffer.toString('utf8'), when this method encounters invalid UTF-8 byte sequences while decoding a Buffer into a string, it replaces each invalid byte with the Unicode replacement character U+FFFD [5][6][7]. This process ensures that the resulting string is valid, though it means information from the original malformed byte sequence is lost during the conversion [8].

Citations:


🏁 Script executed:

#!/bin/bash
set -eu

file=$(git ls-files | rg '(^|/)createHmacToken\.ts$' | head -n 1)
printf '%s\n' "FILE=$file"
wc -l "$file"
sed -n '1,140p' "$file"

printf '\n-- related references --\n'
rg -n --glob '!node_modules' 'createHmacToken|HmacToken|hmac\.update' .

printf '\n-- nearby tests --\n'
git ls-files | rg -i 'hmac|signature|token|http' | head -n 120

Repository: forklaunch/forklaunch

Length of output: 8312


🏁 Script executed:

#!/bin/bash
set -eu

node - <<'JS'
const crypto = require('node:crypto');

const key = 'key';
const raw = Buffer.from([0xff, 0x00, 0xc3, 0x28]);
const decoded = raw.toString('utf8');

const direct = crypto.createHmac('sha256', key).update(raw).digest('hex');
const decodedDigest = crypto.createHmac('sha256', key).update(decoded).digest('hex');
const replacementDigest = crypto.createHmac('sha256', key)
  .update(Buffer.from([0xef, 0xbf, 0xbd, 0x00, 0xef, 0xbf, 0xbd, 0x28]))
  .digest('hex');

console.log(JSON.stringify({
  decodedCodePoints: [...decoded].map((c) => c.codePointAt(0).toString(16)),
  direct,
  decodedDigest,
  replacementDigest,
  decodedChangesBytes: direct !== decodedDigest,
  hmacAcceptsBuffer: direct.length === 64,
}, null, 2));
JS

Repository: forklaunch/forklaunch

Length of output: 552


🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '-- raw-body test --'
sed -n '130,220p' framework/express/__test__/rawBody.webhook.test.ts

printf '%s\n' '-- HMAC generation and verification call sites --'
sed -n '1,110p' framework/core/src/http/generateHmacAuthHeaders.ts
sed -n '210,265p' framework/core/src/http/discriminateAuthMethod.ts
sed -n '1,90p' framework/core/__test__/expressLikeRouterInstantiation.test.ts
sed -n '320,360p' framework/core/__test__/expressLikeRouterInstantiation.test.ts

printf '%s\n' '-- body handling and raw-body capture --'
rg -n -C 5 'rawBody|_rawBody|createHmacToken\(' framework/express framework/core/src/http framework/core/__test__

Repository: forklaunch/forklaunch

Length of output: 21548


🏁 Script executed:

#!/bin/bash
set -eu

node - <<'JS'
const crypto = require('node:crypto');

function current({ method, path, body, timestamp, nonce, secretKey }) {
  const hmac = crypto.createHmac('sha256', secretKey);
  const bodyString = body
    ? `${Buffer.isBuffer(body) ? body.toString('utf8') : typeof body === 'string' ? body : JSON.stringify(body)}\n`
    : undefined;
  hmac.update(`${method}\n${path}\n${bodyString}${timestamp.toISOString()}\n${nonce}`);
  return hmac.digest('hex');
}

function proposed({ method, path, body, timestamp, nonce, secretKey }) {
  const hmac = crypto.createHmac('sha256', secretKey);
  const bodyValue = body
    ? Buffer.isBuffer(body)
      ? body
      : typeof body === 'string'
        ? body
        : JSON.stringify(body)
    : undefined;
  hmac.update(`${method}\n${path}\n`);
  if (Buffer.isBuffer(bodyValue)) {
    hmac.update(bodyValue);
    hmac.update('\n');
  } else {
    hmac.update(`${bodyValue}`);
  }
  hmac.update(`${timestamp.toISOString()}\n${nonce}`);
  return hmac.digest('hex');
}

const base = {
  method: 'POST',
  path: '/hooks',
  timestamp: new Date('2025-01-02T03:04:05.000Z'),
  nonce: 'n',
  secretKey: 'k',
};
for (const body of [
  Buffer.from([0xff, 0x00, 0xc3, 0x28]),
  'text',
  { value: 'text' },
  Buffer.alloc(0),
  '',
  undefined,
]) {
  console.log(JSON.stringify({
    body: Buffer.isBuffer(body) ? `Buffer(${body.toString('hex')})` : body,
    current: current({ ...base, body }),
    proposed: proposed({ ...base, body }),
    same: current({ ...base, body }) === proposed({ ...base, body }),
  }));
}
JS

Repository: forklaunch/forklaunch

Length of output: 1268


Keep Buffer input binary-safe.

Line 38 decodes raw bytes as UTF-8. Invalid bytes become U+FFFD, so the HMAC differs from the received payload. Pass the Buffer directly to hmac.update() and preserve the newline delimiter for all body types. Add a regression test with non-UTF-8 bytes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@framework/core/src/http/createHmacToken.ts` around lines 35 - 45, Update the
body canonicalization in createHmacToken to keep Buffer inputs binary-safe by
passing the original Buffer bytes to hmac.update rather than decoding them as
UTF-8, while retaining the newline delimiter for every body type. Preserve
existing string and object serialization behavior, and add a regression test
using non-UTF-8 bytes to verify the generated HMAC matches the raw payload.

Comment on lines +10 to +11
const PORT = 6480;
const HOST = `http://localhost:${PORT}`;

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.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Avoid a fixed listening port.

Line 10 reserves port 6480. Parallel tests or another local process can cause EADDRINUSE. Bind to port 0, then build the host URL from server.address() after listening.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@framework/express/__test__/rawBody.webhook.test.ts` around lines 10 - 11,
Update the test server setup around PORT and HOST to listen on port 0 instead of
reserving fixed port 6480, then construct the host URL from the actual address
returned by server.address() after the server is listening. Ensure all webhook
requests use this dynamically resolved host.

RohinBhargava and others added 2 commits August 11, 2026 00:12
Floors core at ~1.5.11 and express/hyper-express at ~1.2.38 so fresh
scaffolds are guaranteed the raw-body webhook fix, and aligns blueprint
interface/implementation floors with their latest published versions.

Co-Authored-By: Claude Fable 5 <[email protected]>
Refreshes the vendored skill pack from forklaunch-platform@8ea64815
(.claude/skills) — the previous copy was a July 1 snapshot with 8
drifted files and cli/SKILL.md missing 38% of its content (fl observe,
fl environment).

- refresh all drifted skills; add the new user-facing infra skill
  (fl infra: list/status/resize/config-set/stop/delete)
- remove db-query.md: an internal production-database runbook that
  embeds the production RDS hostname — must not ship to users
- remove gstack, plan-devex-review, plan-design-review: third-party
  workflow tooling flagged in the skill-pack-sync proposal (#243),
  ~200KB of non-ForkLaunch content

Co-Authored-By: Claude Fable 5 <[email protected]>

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cli/assets/forklaunch-skills/backend-patterns/SKILL.md`:
- Around line 1108-1128: Update topologicalSort to track an active visiting set
separately from visited; throw when visit encounters a name already active,
remove names from the active set after dependencies complete, and add them to
visited only before pushing the resolved seeder into ordered. Preserve the
existing dependency traversal and return order for acyclic graphs.

In `@cli/assets/forklaunch-skills/cli/SKILL.md`:
- Around line 406-420: Update the “Remove project components” guidance so piping
“y” into forklaunch delete is documented only for already-approved automation.
Require explicit user approval before executing any piped delete command for
services, workers, libraries, or routers, including the repeated guidance at the
other referenced sections.
- Line 1421: Update the global dry-run guidance in the CLI skill documentation
to apply `--dry-run` only when the command supports it; otherwise instruct users
to use that command’s preview or confirmation flow. Replace the unconditional
“ALWAYS” wording while preserving the intent to preview effects before applying
changes.
- Line 1477: Update the seeder workaround guidance to use the shared
SEEDER_DEPENDENCIES and topologicalSort pattern from the backend seeder guidance
instead of replacing Object.values(seeders) with a manually maintained array;
retain auto-discovery and ensure UserSeeder is included so dependencies
determine execution order.

In `@cli/assets/forklaunch-skills/framework/SKILL.md`:
- Around line 269-281: Update the “Validating schemas programmatically” section
to document that schemify may return either Zod or TypeBox depending on the
configured validator. Use schemaValidator.validate(...) for backend-independent
validation, or split the example into backend-specific Zod and TypeBox flows; do
not present safeParse or result.success as universal APIs.

In `@cli/assets/forklaunch-skills/infra/SKILL.md`:
- Around line 39-41: Update the fenced code block containing the
<project-name>:<resource-type> syntax in SKILL.md to specify the text language
identifier, preserving its contents.
- Around line 101-115: Update the --yes description in the resize command’s
“Safety flags” section to say “non-interactive scripts with an existing JWT
session,” and explicitly retain that CI is unsupported; do not describe --yes as
CI support.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5096ca33-0471-43f5-8a99-ec229321a17c

📥 Commits

Reviewing files that changed from the base of the PR and between ee5660f and e0bc1d3.

📒 Files selected for processing (13)
  • cli/assets/forklaunch-skills/README.md
  • cli/assets/forklaunch-skills/backend-patterns/SKILL.md
  • cli/assets/forklaunch-skills/cli/SKILL.md
  • cli/assets/forklaunch-skills/common-tasks/SKILL.md
  • cli/assets/forklaunch-skills/db-query.md
  • cli/assets/forklaunch-skills/development-guidelines/SKILL.md
  • cli/assets/forklaunch-skills/framework/SKILL.md
  • cli/assets/forklaunch-skills/gstack/SKILL.md
  • cli/assets/forklaunch-skills/infra/SKILL.md
  • cli/assets/forklaunch-skills/infrastructure-and-utilities/SKILL.md
  • cli/assets/forklaunch-skills/plan-design-review/SKILL.md
  • cli/assets/forklaunch-skills/plan-devex-review/SKILL.md
  • cli/assets/forklaunch-skills/platform-architecture/SKILL.md
💤 Files with no reviewable changes (4)
  • cli/assets/forklaunch-skills/db-query.md
  • cli/assets/forklaunch-skills/plan-devex-review/SKILL.md
  • cli/assets/forklaunch-skills/plan-design-review/SKILL.md
  • cli/assets/forklaunch-skills/gstack/SKILL.md

Comment on lines +1108 to +1128
function topologicalSort(
all: typeof seeders,
deps: typeof SEEDER_DEPENDENCIES
): (typeof seeders)[keyof typeof seeders][] {
const ordered: (typeof seeders)[keyof typeof seeders][] = [];
const visited = new Set<string>();

function visit(name: keyof typeof seeders) {
if (visited.has(name)) return;
visited.add(name);
for (const dep of deps[name] ?? []) {
visit(dep);
}
ordered.push(all[name]);
}

for (const name of Object.keys(all) as (keyof typeof seeders)[]) {
visit(name);
}
return ordered;
}

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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Reject cyclic seeder dependencies instead of emitting an invalid order.

The algorithm adds name to visited before visiting its dependencies. For dependencies A -> B and B -> A, the second visit to A returns early, and the function emits an invalid order. DatabaseSeeder.run can then fail on foreign-key constraints.

Track nodes currently being visited separately. Throw when a back-edge is found. Add a node to visited only after all dependencies finish.

Proposed fix
   const ordered: (typeof seeders)[keyof typeof seeders][] = [];
   const visited = new Set<string>();
+  const visiting = new Set<string>();

   function visit(name: keyof typeof seeders) {
     if (visited.has(name)) return;
+    if (visiting.has(name)) {
+      throw new Error(`Cyclic seeder dependency detected at ${String(name)}`);
+    }

-    visited.add(name);
+    visiting.add(name);
     for (const dep of deps[name] ?? []) {
       visit(dep);
     }
+    visiting.delete(name);
+    visited.add(name);
     ordered.push(all[name]);
   }
📝 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
function topologicalSort(
all: typeof seeders,
deps: typeof SEEDER_DEPENDENCIES
): (typeof seeders)[keyof typeof seeders][] {
const ordered: (typeof seeders)[keyof typeof seeders][] = [];
const visited = new Set<string>();
function visit(name: keyof typeof seeders) {
if (visited.has(name)) return;
visited.add(name);
for (const dep of deps[name] ?? []) {
visit(dep);
}
ordered.push(all[name]);
}
for (const name of Object.keys(all) as (keyof typeof seeders)[]) {
visit(name);
}
return ordered;
}
function topologicalSort(
all: typeof seeders,
deps: typeof SEEDER_DEPENDENCIES
): (typeof seeders)[keyof typeof seeders][] {
const ordered: (typeof seeders)[keyof typeof seeders][] = [];
const visited = new Set<string>();
const visiting = new Set<string>();
function visit(name: keyof typeof seeders) {
if (visited.has(name)) return;
if (visiting.has(name)) {
throw new Error(`Cyclic seeder dependency detected at ${String(name)}`);
}
visiting.add(name);
for (const dep of deps[name] ?? []) {
visit(dep);
}
visiting.delete(name);
visited.add(name);
ordered.push(all[name]);
}
for (const name of Object.keys(all) as (keyof typeof seeders)[]) {
visit(name);
}
return ordered;
}
🧰 Tools
🪛 SkillSpector (2.5.1)

[error] 1021: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/assets/forklaunch-skills/backend-patterns/SKILL.md` around lines 1108 -
1128, Update topologicalSort to track an active visiting set separately from
visited; throw when visit encounters a name already active, remove names from
the active set after dependencies complete, and add them to visited only before
pushing the resolved seeder into ordered. Preserve the existing dependency
traversal and return order for acyclic graphs.

Comment on lines +406 to 420
Remove project components.

```bash
# Delete service
forklaunch delete service <service_name>

# Delete worker
forklaunch delete worker <worker_name>

# Delete library
forklaunch delete library <library_name>
**CRITICAL: `delete` always prompts for confirmation and has NO flag to skip it** (`--confirm` is rejected). In scripts, CI, or AI-assistant contexts the prompt fails with `Error: EOF`. The only non-interactive workaround is piping "y" to stdin:

# Delete router (use --path to specify the service directory)
forklaunch delete router <router_name> --path <service_directory>
```bash
# Non-interactive (required for scripts/agents):
printf 'y\n' | forklaunch delete service <service_name> --path .
printf 'y\n' | forklaunch delete worker <worker_name> --path .
printf 'y\n' | forklaunch delete library <library_name> --path .
printf 'y\n' | forklaunch delete router <router_name> --path <service_directory>

# Examples:
forklaunch delete service old-billing
forklaunch delete worker deprecated-processor
forklaunch delete router legacy-api --path ./src/modules/platform-management
printf 'y\n' | forklaunch delete service old-billing --path .
printf 'y\n' | forklaunch delete router legacy-api --path ./src/modules/platform-management
```

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.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Require explicit user approval before piping confirmation into delete commands.

printf 'y\n' | forklaunch delete ... bypasses the CLI's only destructive-action confirmation. This skill is user-invokable by Claude Code, so the workaround can allow an agent to delete a service, worker, library, or router without a separate approval step.

Document the pipe as an already-approved automation technique. Require explicit user approval before executing it.

Also applies to: 762-766, 1411-1416

🧰 Tools
🪛 SkillSpector (2.5.1)

[warning] 493: [EA2] Autonomous Decision Making: Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Remediation: Add human-in-the-loop confirmation for destructive, irreversible, or high-impact operations. Never auto-execute commands that modify files, send data, or alter system state.

(Excessive Agency (EA2))


[warning] 563: [EA2] Autonomous Decision Making: Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Remediation: Add human-in-the-loop confirmation for destructive, irreversible, or high-impact operations. Never auto-execute commands that modify files, send data, or alter system state.

(Excessive Agency (EA2))


[error] 578: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))


[error] 581: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))


[error] 595: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))


[error] 596: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))


[error] 1057: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))


[error] 1058: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))


[error] 1060: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))


[error] 329: [TM2] Chaining Abuse: Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Remediation: Limit tool chaining depth and validate the output of each tool before passing it to the next. Require explicit user approval for multi-step chains.

(Tool Misuse (TM2))


[error] 710: [TM2] Chaining Abuse: Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Remediation: Limit tool chaining depth and validate the output of each tool before passing it to the next. Require explicit user approval for multi-step chains.

(Tool Misuse (TM2))

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/assets/forklaunch-skills/cli/SKILL.md` around lines 406 - 420, Update the
“Remove project components” guidance so piping “y” into forklaunch delete is
documented only for already-approved automation. Require explicit user approval
before executing any piped delete command for services, workers, libraries, or
routers, including the repeated guidance at the other referenced sections.

Source: Linters/SAST tools

- Version gate: a manifest `cli_version` mismatch prompts; non-TTY shows a bare `Error: EOF`.
- Expired login: platform commands silently open a browser device-auth flow and hang headless — check `forklaunch whoami` first.

- ALWAYS use `--dry-run` before applying changes to preview effects

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Qualify the global --dry-run rule.

The word ALWAYS is inaccurate. This file documents commands such as delete that do not provide a --dry-run option. Change the guidance to “Use --dry-run when supported. Otherwise, use the command’s preview or confirmation flow.”

🧰 Tools
🪛 SkillSpector (2.5.1)

[warning] 493: [EA2] Autonomous Decision Making: Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Remediation: Add human-in-the-loop confirmation for destructive, irreversible, or high-impact operations. Never auto-execute commands that modify files, send data, or alter system state.

(Excessive Agency (EA2))


[warning] 563: [EA2] Autonomous Decision Making: Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Remediation: Add human-in-the-loop confirmation for destructive, irreversible, or high-impact operations. Never auto-execute commands that modify files, send data, or alter system state.

(Excessive Agency (EA2))


[error] 578: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))


[error] 581: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))


[error] 595: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))


[error] 596: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))


[error] 1057: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))


[error] 1058: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))


[error] 1060: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))


[error] 329: [TM2] Chaining Abuse: Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Remediation: Limit tool chaining depth and validate the output of each tool before passing it to the next. Require explicit user approval for multi-step chains.

(Tool Misuse (TM2))


[error] 710: [TM2] Chaining Abuse: Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Remediation: Limit tool chaining depth and validate the output of each tool before passing it to the next. Require explicit user approval for multi-step chains.

(Tool Misuse (TM2))

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/assets/forklaunch-skills/cli/SKILL.md` at line 1421, Update the global
dry-run guidance in the CLI skill documentation to apply `--dry-run` only when
the command supports it; otherwise instruct users to use that command’s preview
or confirmation flow. Replace the unconditional “ALWAYS” wording while
preserving the intent to preview effects before applying changes.

- **When a deployed service shows 0 replicas/"Degraded" with no logs, check the dashboard's CloudWatch log source before assuming you need AWS console access.** Dashboard → Monitoring → Logs defaults to a "Live (OTel)" source, which is silent for any crash that happens before the app's own OpenTelemetry collector initializes (e.g. a config-validation failure on boot) — that silence looks identical to "still starting." Switch the log source dropdown from "Live (OTel)" to "CloudWatch" instead: it shows the container's raw stdout/stderr, including the actual stack trace (e.g. `_ConfigInjector.validateConfigSingletons` failures, `Expected number, received nan` on a bad `DB_PORT`, `ELIFECYCLE ... exit code 1`) with no AWS console access required.

- **Empty secrets in generated `.env.local` / `.env.test`** (`ENCRYPTION_KEY=`, `HMAC_SECRET_KEY=`, `BETTER_AUTH_SECRET=`): `pnpm database:setup` fails with `MissingEncryptionKeyError` and tests fail env validation until filled. Generate values before first run: `openssl rand -base64 32` for ENCRYPTION_KEY, `openssl rand -hex 32` for the others. (`forklaunch environment sync` adds missing keys but only with blank values.)
- **iam seeder FK violation** (`account_user_id_foreign`): the generated `persistence/seeders/` omits `user.seeder.ts` even though `seed.data.ts` defines the user, and `DatabaseSeeder` runs seeders via `Object.values(namespace)` which enumerates ALPHABETICALLY (Account before User). Fix: add a `UserSeeder` (mirror `account.seeder.ts`) and replace `Object.values(seeders)` in `persistence/seeder.ts` with an explicit FK-ordered array `[UserSeeder, AccountSeeder, SessionSeeder, VerificationSeeder]`.

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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Use the shared topological-sort seeder guidance.

This workaround recommends replacing Object.values(seeders) with an explicit array. That conflicts with cli/assets/forklaunch-skills/backend-patterns/SKILL.md, Lines 1090-1139, which preserves auto-discovery and uses SEEDER_DEPENDENCIES plus topologicalSort.

The explicit array can omit newly added seeders unless developers update it manually. Update this workaround to use the shared dependency-map pattern, or scope it explicitly to legacy scaffolds.

🧰 Tools
🪛 SkillSpector (2.5.1)

[warning] 493: [EA2] Autonomous Decision Making: Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Remediation: Add human-in-the-loop confirmation for destructive, irreversible, or high-impact operations. Never auto-execute commands that modify files, send data, or alter system state.

(Excessive Agency (EA2))


[warning] 563: [EA2] Autonomous Decision Making: Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Remediation: Add human-in-the-loop confirmation for destructive, irreversible, or high-impact operations. Never auto-execute commands that modify files, send data, or alter system state.

(Excessive Agency (EA2))


[error] 578: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))


[error] 581: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))


[error] 595: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))


[error] 596: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))


[error] 1057: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))


[error] 1058: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))


[error] 1060: [PE3] Credential Access: Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Remediation: Remove references to credential paths. Use environment variables or secrets managers. For docs, use placeholder paths (e.g., /path/to/config). Never load .env or token files in production code paths.

(Privilege Escalation (PE3))


[error] 329: [TM2] Chaining Abuse: Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Remediation: Limit tool chaining depth and validate the output of each tool before passing it to the next. Require explicit user approval for multi-step chains.

(Tool Misuse (TM2))


[error] 710: [TM2] Chaining Abuse: Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Remediation: Limit tool chaining depth and validate the output of each tool before passing it to the next. Require explicit user approval for multi-step chains.

(Tool Misuse (TM2))

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/assets/forklaunch-skills/cli/SKILL.md` at line 1477, Update the seeder
workaround guidance to use the shared SEEDER_DEPENDENCIES and topologicalSort
pattern from the backend seeder guidance instead of replacing
Object.values(seeders) with a manually maintained array; retain auto-discovery
and ensure UserSeeder is included so dependencies determine execution order.

Comment on lines +269 to +281
### Validating schemas programmatically (outside a handler)

To validate a payload against a natural-notation schema directly (e.g. in a unit test, or a script), use `schemaValidator.schemify(...)` to resolve it to the underlying Zod/TypeBox schema, then call that schema's native validation method:

```typescript
import { schemaValidator } from "@{{app-name}}/core";

const compiled = schemaValidator.schemify(MySchema);
const result = compiled.safeParse(payload); // Zod: { success: boolean, data? / error? }
if (!result.success) { /* handle result.error */ }
```

`schemaValidator.compile(...)` is a **different** function — it expects an already-shaped Zod/TypeBox object schema (`ZodObject`/`TObject`), not a natural-notation object literal, and will produce confusing type errors if you pass it a plain schema object. Use `schemify`, not `compile`, when you just want to validate a natural-notation schema. Also note Zod's `safeParse` result has a `success` field, not `ok`.

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n 'schemify|safeParse|TypeCompiler|Value\.Check|class .*SchemaValidator' \
  framework cli blueprint --glob '*.ts' --glob '*.tsx' || true

Repository: forklaunch/forklaunch

Length of output: 12395


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- validator interface and implementations ---'
rg -n -A35 -B10 'compile\(|schemify\(|isValid\(|parse\(' \
  framework/validator/src/shared/types/schema.types.ts \
  framework/validator/src/zod/zodSchemaValidator.ts \
  framework/validator/src/typebox/typeboxSchemaValidator.ts

printf '%s\n' '--- validator selection and exports ---'
rg -n -A25 -B15 'ZodSchemaValidator|TypeboxSchemaValidator|schemaValidator|VALIDATOR|validator' \
  framework/core framework/validator --glob '*.ts' | head -n 500

printf '%s\n' '--- documentation context ---'
sed -n '250,305p' cli/assets/forklaunch-skills/framework/SKILL.md

Repository: forklaunch/forklaunch

Length of output: 50377


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- compile implementations ---'
rg -n -A18 -B8 'compile' \
  framework/validator/src/zod/zodSchemaValidator.ts \
  framework/validator/src/typebox/typeboxSchemaValidator.ts \
  framework/validator/src/shared/types/schema.types.ts

printf '%s\n' '--- validator factory and configuration ---'
rg -n -A30 -B15 'new (Zod|Typebox)SchemaValidator|ZodSchemaValidator|TypeboxSchemaValidator|schemaValidator' \
  framework/validator/src framework/core/src \
  --glob '*.ts' | grep -E '(^framework/|new |SchemaValidator|schemaValidator|validator)' | head -n 300

printf '%s\n' '--- exact documentation ---'
sed -n '265,285p' cli/assets/forklaunch-skills/framework/SKILL.md

Repository: forklaunch/forklaunch

Length of output: 40422


Document backend-specific validation.

schemify returns a Zod schema or a TypeBox schema, based on the selected validator. safeParse and result.success apply only to Zod. Use schemaValidator.validate(...) for backend-independent validation, or provide separate Zod and TypeBox examples.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/assets/forklaunch-skills/framework/SKILL.md` around lines 269 - 281,
Update the “Validating schemas programmatically” section to document that
schemify may return either Zod or TypeBox depending on the configured validator.
Use schemaValidator.validate(...) for backend-independent validation, or split
the example into backend-specific Zod and TypeBox flows; do not present
safeParse or result.success as universal APIs.

Comment on lines +39 to +41
```
<project-name>:<resource-type>
```

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add a language identifier to the fenced code block.

The block contains identifier syntax. Mark it as text to satisfy markdownlint and keep documentation lint clean.

🧰 Tools
🪛 markdownlint-cli2 (0.23.2)

[warning] 39-39: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/assets/forklaunch-skills/infra/SKILL.md` around lines 39 - 41, Update the
fenced code block containing the <project-name>:<resource-type> syntax in
SKILL.md to specify the text language identifier, preserving its contents.

Source: Linters/SAST tools

Comment on lines +101 to +115
fl infra resize <project>:<type> --environment <env> [sizing flags] [--snapshot-before-change] [--yes|-y] [--dry-run] [--resource-id <id>]

# Sizing flags (pass at least one, or it fails fast before any network call):
--instance-class <class> # database, e.g. db.t3.small
--allocated-storage <GB> # database
--node-type <type> # cache
--num-cache-nodes <n> # cache
--number-of-broker-nodes <n> # queue (Kafka/MSK)
--ebs-storage-size <GB> # queue

# Safety flags:
--snapshot-before-change # database only
-y, --yes # skip the confirmation prompt (CI/scripted)
--dry-run # resolve + fetch current config + print diff, then STOP —
# no confirm prompt, no PATCH/deploy call, no AWS mutation

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Do not describe --yes as CI support.

Lines 33-35 state that fl infra does not support HMAC or CI authentication. Line 113 labels --yes as “CI/scripted”, but this flag only skips confirmation. It does not provide the required JWT session.

Change the description to “non-interactive scripts with an existing JWT session” and keep CI explicitly unsupported.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/assets/forklaunch-skills/infra/SKILL.md` around lines 101 - 115, Update
the --yes description in the resize command’s “Safety flags” section to say
“non-interactive scripts with an existing JWT session,” and explicitly retain
that CI is unsupported; do not describe --yes as CI support.

@RohinBhargava
RohinBhargava merged commit 84e04cc into main Aug 11, 2026
16 checks passed
@RohinBhargava
RohinBhargava deleted the rohin/raw-body-webhooks branch August 11, 2026 07:31
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