Skip to content

Release Readiness intelligence platform — foundation (Phases 0–2)#51

Open
ChrisAdamsdevelopment wants to merge 7 commits into
mainfrom
feat/trust-platform-foundation
Open

Release Readiness intelligence platform — foundation (Phases 0–2)#51
ChrisAdamsdevelopment wants to merge 7 commits into
mainfrom
feat/trust-platform-foundation

Conversation

@ChrisAdamsdevelopment

@ChrisAdamsdevelopment ChrisAdamsdevelopment commented Jun 21, 2026

Copy link
Copy Markdown
Owner

What this is

The foundation for SpectraCleanse's evolution from a metadata utility into a Release Readiness Intelligence Platform — the system a creator runs before distribution to answer: "Can I safely release this today, and if not, exactly what should I fix first?"

Everything here is additive and gated behind feature flags that are off by default, so production behavior is unchanged until flags are enabled. main (the live app: cleanse, billing, auth) is untouched.

What changed

Phase 0 — feature flags + safe migration

  • server/featureFlags.js + src/utils/featureFlags.ts (off by default, unknown names ignored), GET /api/features, FEATURES / VITE_FEATURES env.

Phase 1 — intelligence framework (server/readiness/)

  • Findings schema, scoring engine, verdict engine (with an "honesty cap" — never "Ready" on un-assessed required categories), a safe declarative compliance-rule evaluator (no eval), report orchestrator, and a flag-gated provider registry that modules plug into.
  • Storage (releases + release_reports, additive tables) and flag-gated API: POST /api/releases, GET /api/releases, GET /api/releases/:id, POST /api/releases/:id/check.
  • A gated Release readiness dashboard view in the app: verdict-led, top issues, per-finding what / why / business impact / fix / est. time / score gain, expandable education, visible "not assessed".

Phase 2 — metadata validation provider

  • server/readiness/providers/metadata.js + registerProviders.js, gated by metadata_validation. Findings are authored as risk (business impact, plain-English why, concrete fix), not technical nitpicks. With both flags on, the dashboard produces a real scored verdict.

Specs / docs

  • release-readiness-spec.md (findings schema, scoring, verdict, report, rule registry — founder-approved decisions), release-risk-and-packaging.md (risk/readiness/scoring definitions; packaging deferred, Stripe frozen), feature-flags-and-migration.md.

Why

Platforms are shifting from "hide AI" toward disclosure, rights verification, and release compliance. The durable, defensible product helps creators pass release checks — reframing the existing engine (which already does marker detection, hashing, verification) around trust and readiness, under the same sovereignty ethos (the creator gets the knowledge and control).

Reviewer notes

  • Nothing is enabled in production. No FEATURES set ⇒ identical to today. Auth/billing/cleanse are not gated on any flag.
  • Tests: 42 passing, 2 skipped. The 2 skipped are the storage integration tests — better-sqlite3 is built for the Node 20 runtime and can't load under a newer local Node ABI; they run on CI (Node 20). For the same reason the server wasn't booted locally (only node --check + tsc --noEmit, both clean).
  • Scope deliberately excluded: packaging/pricing and any Stripe changes are deferred (see release-risk-and-packaging.md §4a). No Stripe IDs, subscribers, or plan names are touched.
  • Suggested review path: release-readiness-spec.mdserver/readiness/ (findings → scoring → verdict → report) → providers/metadata.js → the dashboard in src/components/ReleaseReadiness.tsx.

🤖 Generated with Claude Code

Summary by Sourcery

Introduce a flag-gated Release Readiness intelligence framework, including backend storage, APIs, scoring and verdict engines, and a new dashboard UI, all disabled by default to keep existing production behavior unchanged.

New Features:

  • Add a feature-flag system and public /api/features endpoint to control rollout of new trust/compliance capabilities.
  • Implement a Release Readiness engine with providers, findings schema, scoring, verdict, reporting, and persistence for releases and their reports.
  • Expose new flag-gated APIs and frontend dashboard for running and viewing release readiness checks, including a metadata validation provider as the first module.

Enhancements:

  • Document the Release Readiness architecture, risk/scoring philosophy, and feature-flag/migration strategy for phased rollout.

Tests:

  • Add unit and integration tests covering the readiness engine, rule registry, provider gating, feature flags, metadata provider, and persistence layer, with sqlite-backed tests skipped when the native binding is unavailable locally.

ChrisAdamsdevelopment and others added 2 commits June 21, 2026 10:24
Foundation for the pivot from metadata utility to a Release Readiness
Intelligence Platform. All new behavior is gated behind feature flags
(off by default), so production is unchanged until flags are enabled.

Phase 0 — feature-flag + branch scaffolding:
- server/featureFlags.js, src/utils/featureFlags.ts (flags off by default,
  unknown names ignored), GET /api/features, FEATURES/VITE_FEATURES env.

Phase 1 — intelligence framework (server/readiness/):
- findings schema, scoring engine, verdict engine (with honesty cap),
  safe declarative compliance rule evaluator (no eval), report orchestrator,
  flag-gated provider registry.
- Storage (releases + release_reports) and flag-gated API:
  POST /api/releases, GET /api/releases, GET /api/releases/:id,
  POST /api/releases/:id/check.
- Gated "Release readiness" dashboard view in the app (verdict-led, top
  issues, per-finding what/why/impact/fix/est-time/score-gain, expandable
  education, visible "not assessed").

Specs/docs: release-readiness-spec.md, release-risk-and-packaging.md
(risk/readiness/scoring definitions; packaging deferred, Stripe frozen),
feature-flags-and-migration.md.

Tests: 35 passing; store test runs on CI (Node 20) where the native
better-sqlite3 binding is available.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
First real CheckProvider feeding the Release Readiness framework. Findings
are authored as risk (businessImpact, why, how-to-fix, estimated fix time,
score impact) rather than technical observations.

- server/readiness/providers/metadata.js: validateMetadata() + metadataProvider
  (category metadata, flag metadata_validation) — required fields, placeholder/
  featured-in-title/formatting/whitespace/control-char checks, copyright + rights,
  discoverability, and AI-marker residue reused from existing file analysis.
- server/readiness/registerProviders.js: registers built-in providers; required
  once in server.js so getEnabledProviders() picks them up at runtime.

With metadata_validation + release_readiness enabled, the dashboard now produces
a real scored verdict instead of an all-"not assessed" report.

Tests: 42 passing (store test CI/Node 20 only).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 21, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spectracleanseai Ready Ready Preview, Comment, Open in v0 Jun 23, 2026 8:52pm

@sourcery-ai

sourcery-ai Bot commented Jun 21, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds a flag-gated Release Readiness intelligence framework (findings/scoring/verdict/report engines, provider registry, storage, and API), a metadata validation provider, and a new SPA dashboard view, all behind feature flags that default off so existing cleanse/auth/billing behavior is unchanged.

Sequence diagram for Release Readiness check flow

sequenceDiagram
  actor User
  participant ReleaseReadiness as ReleaseReadiness_component
  participant ReadinessClient as readinessClient
  participant API as API_Server
  participant Store as readinessStore
  participant Providers as providers
  participant Metadata as metadataProvider
  participant Report as generateReport

  User->>ReleaseReadiness: click Run readiness check
  ReleaseReadiness->>ReadinessClient: runReadinessCheck(apiBaseUrl, authToken, input)
  ReadinessClient->>ReadinessClient: createRelease(apiBaseUrl, token, input)
  ReadinessClient->>API: POST /api/releases
  API->>Store: createRelease(userId, releaseInput)
  Store-->>API: release
  API-->>ReadinessClient: { release }
  ReadinessClient->>ReadinessClient: checkRelease(apiBaseUrl, token, releaseId)
  ReadinessClient->>API: POST /api/releases/:id/check
  API->>Store: getRelease(userId, releaseId)
  Store-->>API: release
  API->>Providers: getEnabledProviders()
  API->>Report: generateReport({ releaseId, context, providers, ruleRegistryVersion })
  loop for each enabled provider
    Report->>Metadata: evaluate(context)
    Metadata-->>Report: findings
  end
  Report-->>API: report
  API->>Store: saveReport(releaseId, report)
  API-->>ReadinessClient: { report }
  ReadinessClient-->>ReleaseReadiness: ReadinessReport
  ReleaseReadiness-->>User: display verdict and prioritized fixes
Loading

File-Level Changes

Change Details Files
Introduce environment-driven feature flag system and expose enabled features to the SPA.
  • Add server-side feature flag parsing and helpers backed by FEATURES env and ignore unknown flags
  • Add frontend feature flag parser and runtime /api/features consumption helpers
  • Expose GET /api/features endpoint returning currently enabled features
server/featureFlags.js
src/utils/featureFlags.ts
server.js
Add Release Readiness domain model, scoring, verdict, rule registry engines, and persistence layer.
  • Define canonical finding schema, scoring engine, verdict logic, and configuration constants for weights/thresholds
  • Implement declarative compliance rule registry and condition evaluator without eval
  • Implement report generator that runs providers, scores findings, applies verdicts, and shapes the persisted report with prioritized fixes and top issues
  • Add SQLite-backed releases and release_reports tables and accessors, wired into server startup
server/readiness/findings.js
server/readiness/scoring.js
server/readiness/verdict.js
server/readiness/ruleRegistry.js
server/readiness/config.js
server/readiness/report.js
server/readiness/store.js
server.js
Expose Release Readiness REST API and integrate with a provider registry gated by feature flags.
  • Add provider registry abstraction and built-in provider registration hook
  • Wire readiness routes for creating/listing/fetching releases and triggering checks, guarded by auth and release_readiness flag
  • Ensure readiness checks call enabled providers and persist reports
server/readiness/providers.js
server/readiness/registerProviders.js
server/readiness/store.js
server/readiness/report.js
server.js
Implement metadata validation provider as the first readiness module, authored in terms of business risk.
  • Add metadata provider that inspects release metadata and optional analysis to emit risk-focused findings with what/why/impact/how-to-fix and estimated fix time
  • Gate metadata provider behind metadata_validation feature flag and register it with the provider registry
server/readiness/providers/metadata.js
server/readiness/registerProviders.js
tests/readiness-metadata-provider.test.ts
Add Release Readiness SPA dashboard and client utilities, toggled via feature flag and integrated into the existing app shell.
  • Introduce readiness client API wrapper to create releases and run checks, plus presentation helpers for verdict/category labels
  • Add ReleaseReadiness React component providing metadata form, verdict-led report view, prioritized fixes, and category score visualization
  • Add Cleanse/Readiness toggle in App component driven by enabledFeatures from /api/features and switch main content accordingly
src/utils/readinessClient.ts
src/components/ReleaseReadiness.tsx
app.tsx
Document the readiness architecture, risk/packaging framing, and feature-flag migration strategy.
  • Add foundational readiness spec covering findings schema, scoring, verdict, report, and rule registry plus phase plan
  • Add release risk/readiness/packaging framing document deferring any Stripe changes to a later report
  • Add feature-flag and migration doc describing safe rollout and environment model
spectracleanse-engineering/docs/release-readiness-spec.md
spectracleanse-engineering/docs/release-risk-and-packaging.md
spectracleanse-engineering/docs/feature-flags-and-migration.md
Add test coverage for feature flags, readiness engines, provider gating, and store behavior.
  • Add unit tests for feature flag parsing and env handling
  • Add unit tests for findings normalization, scoring, verdict logic, rule registry evaluation, report generation, provider registry gating, metadata provider, and readiness store persistence (with SQLite guard)
tests/feature-flags.test.ts
tests/readiness-engine.test.ts
tests/readiness-metadata-provider.test.ts
tests/readiness-store.test.ts

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've found 4 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="server/readiness/ruleRegistry.js" line_range="36-45" />
<code_context>
+  if (Array.isArray(condition.all)) return condition.all.every((c) => evaluateCondition(c, context));
+  if (Array.isArray(condition.any)) return condition.any.some((c) => evaluateCondition(c, context));
+  if (condition.not) return !evaluateCondition(condition.not, context);
+  if (typeof condition.field === 'string' && typeof condition.op === 'string') {
+    const op = OPS[condition.op];
+    if (!op) return false;
+    return Boolean(op(getField(context, condition.field), condition.value));
+  }
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Consider failing fast or logging when a rule uses an unknown operator instead of silently returning false.

Right now, an unknown `condition.op` just returns `false`, effectively disabling the rule (e.g. `

```suggestion
function evaluateCondition(condition, context) {
  if (!condition || typeof condition !== 'object') return false;
  if (Array.isArray(condition.all)) return condition.all.every((c) => evaluateCondition(c, context));
  if (Array.isArray(condition.any)) return condition.any.some((c) => evaluateCondition(c, context));
  if (condition.not) return !evaluateCondition(condition.not, context);
  if (typeof condition.field === 'string' && typeof condition.op === 'string') {
    const op = OPS[condition.op];

    if (!op) {
      // Fail fast-ish: log unknown operator usage so misconfigured rules are discoverable.
      // We keep returning false to preserve existing behaviour while adding observability.
      // eslint-disable-next-line no-console
      console.warn(
        `[readiness] Unknown operator "${condition.op}" in condition for field "${condition.field}". ` +
          'This rule will evaluate to false.'
      );
      return false;
    }

    return Boolean(op(getField(context, condition.field), condition.value));
  }
```
</issue_to_address>

### Comment 2
<location path="tests/feature-flags.test.ts" line_range="4-9" />
<code_context>
+import { describe, expect, it } from 'vitest';
+const { parseFeatures, getEnabledFeatures, isFeatureEnabled, KNOWN_FEATURES } = require('../server/featureFlags');
+
+describe('feature flag parsing', () => {
+  it('returns no features for empty / undefined input (production default is off)', () => {
+    expect(parseFeatures('')).toEqual([]);
+    expect(parseFeatures(undefined)).toEqual([]);
+    expect(parseFeatures(null)).toEqual([]);
+  });
+
+  it('parses known features and is case/whitespace insensitive', () => {
</code_context>
<issue_to_address>
**suggestion (testing):** Server-side feature-flag tests are thorough; consider mirroring coverage on the frontend helper

The server tests validate parsing, normalization, unknown-name handling, de-duplication, and env injection, but `src/utils/featureFlags.ts` adds client-side logic (`parseFeatures`, `getBuildTimeFeatures`, `isFeatureEnabled`, `fetchEnabledFeatures`) that currently lacks coverage. Please add a small Vitest suite to verify:
- `parseFeatures` matches server behavior
- `fetchEnabledFeatures` returns `[]` on non-200 responses and network errors
- `getBuildTimeFeatures` respects `import.meta.env.VITE_FEATURES`
This will help keep server and client feature-flag behavior aligned and avoid regressions.

Suggested implementation:

```typescript
import { describe, expect, it, vi } from 'vitest';

// Server-side feature flags (existing tests)
const {
  parseFeatures,
  getEnabledFeatures,
  isFeatureEnabled,
  KNOWN_FEATURES,
} = require('../server/featureFlags');

// Client-side feature flags (new tests)
import * as clientFeatureFlags from '../src/utils/featureFlags';

```

To fully implement the requested coverage, please append a new `describe` block near the end of `tests/feature-flags.test.ts` (outside the server-side `describe`) with tests similar to:

```ts
describe('client feature flags', () => {
  describe('parseFeatures (client)', () => {
    it('matches server parseFeatures behavior for known features', () => {
      expect(clientFeatureFlags.parseFeatures(' Chain_Of_Custody , release_readiness '))
        .toEqual(['chain_of_custody', 'release_readiness']);
    });

    it('returns [] for empty / undefined / null input', () => {
      expect(clientFeatureFlags.parseFeatures('')).toEqual([]);
      // @ts-expect-error intentional undefined
      expect(clientFeatureFlags.parseFeatures(undefined)).toEqual([]);
      // @ts-expect-error intentional null
      expect(clientFeatureFlags.parseFeatures(null)).toEqual([]);
    });

    it('ignores unknown feature names', () => {
      expect(
        clientFeatureFlags.parseFeatures('chain_of_custody,not_a_real_flag,DROP TABLE'),
      ).toEqual(['chain_of_custody']);
    });
  });

  describe('getBuildTimeFeatures', () => {
    const originalEnv = { ...(import.meta as any).env };

    afterEach(() => {
      (import.meta as any).env = { ...originalEnv };
    });

    it('returns [] when VITE_FEATURES is not set', () => {
      (import.meta as any).env = { ...originalEnv };
      delete (import.meta as any).env.VITE_FEATURES;

      expect(clientFeatureFlags.getBuildTimeFeatures()).toEqual([]);
    });

    it('parses VITE_FEATURES using the same rules as parseFeatures', () => {
      (import.meta as any).env = {
        ...originalEnv,
        VITE_FEATURES: ' Chain_Of_Custody , release_readiness ',
      };

      expect(clientFeatureFlags.getBuildTimeFeatures()).toEqual([
        'chain_of_custody',
        'release_readiness',
      ]);
    });
  });

  describe('fetchEnabledFeatures', () => {
    const originalFetch = global.fetch;

    afterEach(() => {
      global.fetch = originalFetch;
      vi.restoreAllMocks();
    });

    it('returns [] when the response status is not 200', async () => {
      global.fetch = vi.fn().mockResolvedValue({
        ok: false,
        status: 500,
        json: vi.fn(),
      });

      const features = await clientFeatureFlags.fetchEnabledFeatures();
      expect(features).toEqual([]);
    });

    it('returns [] on network errors', async () => {
      global.fetch = vi.fn().mockRejectedValue(new Error('network error'));

      const features = await clientFeatureFlags.fetchEnabledFeatures();
      expect(features).toEqual([]);
    });

    it('returns parsed feature list on 200 responses', async () => {
      global.fetch = vi.fn().mockResolvedValue({
        ok: true,
        status: 200,
        json: vi.fn().mockResolvedValue({ features: ['chain_of_custody'] }),
      });

      const features = await clientFeatureFlags.fetchEnabledFeatures();
      expect(features).toEqual(['chain_of_custody']);
    });
  });
});
```

These tests assume:
- `parseFeatures` in `src/utils/featureFlags.ts` mirrors the server behavior (normalization, unknown-name filtering).
- `getBuildTimeFeatures` reads `import.meta.env.VITE_FEATURES` and delegates to `parseFeatures`.
- `fetchEnabledFeatures` uses `fetch`, returns `[]` on non-OK statuses or errors, and returns a feature list (or `[]`) on success.

Adjust the exact expectations (response shape, env var name, etc.) if your current implementation differs.
</issue_to_address>

### Comment 3
<location path="spectracleanse-engineering/docs/release-risk-and-packaging.md" line_range="73" />
<code_context>
+
+The tiering below is a working hypothesis to guide entitlement architecture, **not a committed packaging decision.** Final names, bundles, and tiers are deferred to the Packaging & Monetization Report (§4a) after Phase 2.
+
+Value grouped by *which risks we help you retire*, with clear personas and upgrade triggers. (Pricing intentionally omitted.)
+
+| Tier | Persona | Value: risks addressed | Representative features |
</code_context>
<issue_to_address>
**suggestion (typo):** Consider adding a verb so this sentence reads more clearly (e.g., "Value is grouped by …").

The clause “Value grouped by *which risks we help you retire*” is grammatically a fragment. Consider “Value is grouped by *which risks we help you retire*” (or similar) to make it a complete sentence while preserving the meaning.

```suggestion
Value is grouped by *which risks we help you retire*, with clear personas and upgrade triggers. (Pricing intentionally omitted.)
```
</issue_to_address>

### Comment 4
<location path="spectracleanse-engineering/docs/release-risk-and-packaging.md" line_range="77" />
<code_context>
+
+| Tier | Persona | Value: risks addressed | Representative features |
+|---|---|---|---|
+| **Free — Scan** | Curious / first-time creator | See *that* risk exists | Basic release scan, verdict + top issues, limited scans/month, no export, metadata cleanse (existing) |
+| **Creator** | Active independent / AI-assisted creator | Retire metadata + disclosure risk | Full readiness reports, metadata validation, AI disclosure guidance, unlimited scans, export, batch-lite |
+| **Pro** (today's "Studio") | Serious / frequent releaser | Retire rights + platform risk | Everything in Creator + rights validation, platform-compliance packs, advanced/exportable reports, full batch |
</code_context>
<issue_to_address>
**suggestion (typo):** Slightly adjust the Free tier description to read more naturally (e.g., "See that a risk exists").

The current phrasing is slightly ungrammatical. Updating it to “See *that a* risk exists” would make the description read more smoothly while preserving the meaning.

```suggestion
| **Free — Scan** | Curious / first-time creator | See *that a* risk exists | Basic release scan, verdict + top issues, limited scans/month, no export, metadata cleanse (existing) |
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread server/readiness/ruleRegistry.js
Comment thread tests/feature-flags.test.ts
Comment thread spectracleanse-engineering/docs/release-risk-and-packaging.md Outdated
Comment thread spectracleanse-engineering/docs/release-risk-and-packaging.md Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7f8b06d858

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread app.tsx
Comment thread src/components/ReleaseReadiness.tsx
…oundation

# Conflicts:
#	.env.example
#	app.tsx
#	server.js

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2ea176de2e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/readiness/providers/metadata.js Outdated
CI: the npm audit gate failed on high/critical CVEs in build/test tooling
(vite, vitest, esbuild) that never execute in the production runtime, plus
real runtime highs (multer, nodemailer).
- Reclassify build/test/frontend-only packages as devDependencies (verified
  the runtime server requires none of them; dist/ is prebuilt in the Docker
  builder stage). Also slims the production image.
- Scope the audit gate to production deps: `npm audit --omit=dev --audit-level=high`.
- Patch runtime highs: multer ^2.2.0 (non-breaking), nodemailer ^9.0.1.

Review feedback:
- ruleRegistry: warn on unknown rule operators instead of silently disabling.
- readinessClient: throw ReadinessApiError carrying HTTP status so the dashboard
  logs out on 401 (expired token), matching the cleanse flow.
- ReleaseReadiness: pass file analysis into the check so AI-marker / parse
  findings fire; key 401 handling off status.
- Add client-side feature-flag tests (parse/build-time/fetch).
- Doc grammar fixes in release-risk-and-packaging.md.

Tests: 65 passing, 2 skipped (sqlite store test, CI/Node 20 only).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The whitespace check compared the already-trimmed value against its own
trimmed form, so leading/trailing spaces were never caught. Compare the raw
field value vs. trimmed (and check doubled spaces / control chars on raw),
so titles/artists/copyright like ' My Song ' now correctly warn.

Adds a regression test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a3e4efe6e9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server.js

app.post('/api/releases', requireAuth, requireFeature('release_readiness'), (req, res) => {
const { title, platform, metadata, analysis, targets } = req.body || {};
const context = { metadata: metadata || {}, analysis: analysis || null, targets: targets || null };

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Bound persisted release context size

When release_readiness is enabled, this copies arbitrary metadata, analysis, and targets from the global 10 MB JSON body into context_json; running a check then persists a report that includes the same context as inputsSnapshot. Because these new write routes have no plan/usage cap, an authenticated user can repeatedly POST large targets/analysis payloads and grow the SQLite database until the disk fills, even without uploading files. Whitelist the expected scalar fields or add a much smaller per-release size/retention limit before persisting.

Useful? React with 👍 / 👎.

Comment thread .github/workflows/ci.yml Outdated
# the production runtime. Build/test tooling (vite, vitest, esbuild, etc.)
# lives in devDependencies and never executes in the deployed server, so
# it is excluded here to keep the gate focused on real production risk.
run: npm audit --omit=dev --audit-level=high

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 Badge Audit browser-shipped dependencies before deploy

This CI gate now runs npm audit --omit=dev, and I checked npm audit --help where --omit <dev|optional|peer> is the option that excludes dev dependencies. In this same change, browser-executed packages such as browser-id3-writer and music-metadata are under devDependencies but are imported by src/utils/metadata.js and bundled into the production SPA, so high/critical CVEs in code shipped to users' browsers no longer block the CI workflow that cd.yml waits on before deployment. Keep a separate frontend audit or don't omit those bundled runtime packages from the blocking audit.

Useful? React with 👍 / 👎.

…ach)

Resolves conflicts in package.json / package-lock.json after PR #54 (root audit
fix) merged to main. main is canonical: keep its dependency upgrades
(vite 7, vitest 4, @vitejs/plugin-react 5, multer 2.2, nodemailer 9) and its
full `npm audit --audit-level=high` gate.

Deliberately drops this branch's earlier divergent audit approach (--omit=dev +
dependency reclassification) so the merge does NOT revert #54's hardening or
weaken the CI gate. All release-readiness feature code on this branch is kept.

Verified: node --check server.js OK, tsc --noEmit OK, vitest 66 passed / 2
skipped (sqlite store test, CI-only), npm audit --audit-level=high exit 0.
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