Skip to content
Open
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
80 changes: 26 additions & 54 deletions .snyk
Original file line number Diff line number Diff line change
@@ -1,57 +1,52 @@
version: v1.5.0
ignore:
'SNYK-JS-SIRV-12558119':
- '* > sirv@2.0.4':
reason: 'Transitive dependency in Docusaurus; not exploitable in static site serving context (dev-only asset handler)'
expires: '2026-07-28T00:00:00.000Z'
created: '2025-11-06T15:57:00.000Z'
'SNYK-JS-JSYAML-13961110':
- '* > js-yaml':
reason: 'Transitive dependency in Docusaurus; upgrade path blocked until https://github.com/jonschlinkert/gray-matter/pull/137#issuecomment-3533768351 is merged and transitive deps are updated. Not exploitable in current usage.'
expires: '2026-07-28T00:00:00.000Z'
expires: '2026-09-30T00:00:00.000Z'
created: '2025-11-17T09:06:00.000Z'
'SNYK-JS-NODEFORGE-14114940':
- '* > node-forge':
reason: 'Transitive dependency in Docusaurus; not exploitable in current usage.'
expires: '2026-07-28T00:00:00.000Z'
expires: '2026-09-30T00:00:00.000Z'
created: '2025-11-26T10:12:00.000Z'
'SNYK-JS-EXPRESS-14157151':
- '@docusaurus/core@3.9.2 > * > express':
reason: 'Transitive dependency in Docusaurus; not exploitable in current usage.'
expires: '2026-07-28T00:00:00.000Z'
expires: '2026-09-30T00:00:00.000Z'
created: '2025-12-02T09:39:00.000Z'
- '@docusaurus/plugin-content-docs@3.9.2 > * > express':
reason: 'Transitive dependency in Docusaurus; not exploitable in current usage.'
expires: '2026-07-28T00:00:00.000Z'
expires: '2026-09-30T00:00:00.000Z'
created: '2025-12-02T09:39:00.000Z'
- '@docusaurus/preset-classic@3.9.2 > * > express':
reason: 'Transitive dependency in Docusaurus; not exploitable in current usage.'
expires: '2026-07-28T00:00:00.000Z'
expires: '2026-09-30T00:00:00.000Z'
created: '2025-12-02T09:39:00.000Z'
'SNYK-JS-QS-14724253':
- '* > qs@6.14.0':
reason: 'Transitive dependency in @apollo/server, body-parser; not exploitable in current usage.'
expires: '2026-07-28T00:00:00.000Z'
expires: '2026-09-30T00:00:00.000Z'
created: '2026-01-28T00:00:00.000Z'
- '* > qs@6.13.0':
reason: 'Transitive dependency in express, @docusaurus/core; not exploitable in current usage.'
expires: '2026-07-28T00:00:00.000Z'
expires: '2026-09-30T00:00:00.000Z'
created: '2026-01-28T00:00:00.000Z'
'SNYK-JS-PNPMNPMCONF-14897556':
- '* > @pnpm/npm-conf@2.3.1':
reason: 'Transitive dependency in @docusaurus/core; not exploitable in current usage.'
expires: '2026-07-28T00:00:00.000Z'
created: '2026-01-08T11:04:00.000Z'
'SNYK-JS-UNDICI-14943963':
- '* > undici':
reason: 'Transitive dependency in @azure/functions; upgrade path has type errors'
expires: '2026-07-28T00:00:00.000Z'
expires: '2026-09-30T00:00:00.000Z'
created: '2026-01-15T11:04:00.000Z'
'SNYK-JS-YAUZL-15467445':
- '* > yauzl@<3.2.1':
reason: 'Transitive dependency in @mongodb-memory-server; not exploitable in current usage.'
expires: '2026-03-26T00:00:00.000Z'
created: '2026-03-12T12:35:00.000Z'
'SNYK-JS-ELLIPTIC-14908844':
- '* > elliptic@6.6.1':
reason: 'Transitive dependency of vite-plugin-node-polyfills in the dev-only browser build toolchain. This package is not used for application cryptographic signing, and Snyk reports no fixed npm release.'
expires: '2026-09-30T00:00:00.000Z'
created: '2026-07-30T00:00:00.000Z'
'SNYK-JS-MORGAN-17135841':
- '* > morgan@1.10.1':
reason: 'Transitive dependency of Azurite in the API development emulator only. It is not included in production application dependencies, and no patched morgan release is available in the configured registry.'
expires: '2026-09-30T00:00:00.000Z'
created: '2026-07-30T00:00:00.000Z'
'SNYK-JS-UUID-16133035':
- '* > uuid@8.3.2':
reason: 'Transitive dependency in Docusaurus and Azurite dev-only stacks; no compatible fix path available yet from upstream.'
Expand All @@ -66,16 +61,6 @@ ignore:
reason: 'Apollo usage-reporting-protobuf depends on @apollo/protobufjs and Snyk reports no fixed version. We are accepting this temporarily until Apollo provides a non-vulnerable upgrade path.'
expires: '2026-07-31T00:00:00.000Z'
created: '2026-04-30T00:00:00.000Z'
'SNYK-JS-MONGOOSE-16425765':
- '* > mongoose@8.17.0':
reason: 'Mongoose 8.22.1 has TypeScript constraint errors in type definitions (types/inferrawdoctype.d.ts, types/inferschematype.d.ts) that break compilation. Patch attempts failed due to external library type incompatibilities. Risk is Low: requires control of query field names and values.'
expires: '2026-11-07T00:00:00.000Z'
created: '2026-05-07T09:00:00.000Z'
'SNYK-JS-BABELPLUGINTRANSFORMMODULESSYSTEMJS-16624576':
- '* > @babel/plugin-transform-modules-systemjs@7.28.5':
reason: 'Transitive dependency in Docusaurus; not exploitable in current usage.'
expires: '2026-06-28T00:00:00.000Z'
created: '2026-05-11T10:00:00.000Z'
'SNYK-JS-AI-16734889':
- '@docusaurus/preset-classic@3.10.1 > * > ai@5.0.105':
reason: 'Transitive dependency in Docusaurus docsearch; Snyk reports no fixed upgrade or patch available.'
Expand All @@ -91,39 +76,21 @@ ignore:
reason: 'Transitive dependency in Docusaurus docsearch; Snyk reports no fixed upgrade or patch available.'
expires: '2026-09-18T00:00:00.000Z'
created: '2026-06-08T00:00:00.000Z'
'SNYK-JS-OPENTELEMETRYEXPORTERPROMETHEUS-16758050':
- '* > @opentelemetry/exporter-prometheus@0.57.2':
reason: 'Requires upgrade of @opentelemetry/sdk-node to 0.217.0, which has type errors that break compilation. Created task to upgrade OTEL service to 2.x and resolve vulnerability that way.'
expires: '2026-07-28T00:00:00.000Z'
created: '2026-06-01T10:00:00.000Z'
'SNYK-JS-POSTCSSSELECTORPARSER-16873882':
- '* > postcss-selector-parser':
reason: 'Transitive dependency in Docusaurus CSS optimization/build tooling; Snyk reports no fixed upgrade or patch available. Not exploitable at runtime because docs CSS is repository-controlled and processed at build time.'
expires: '2026-09-18T00:00:00.000Z'
created: '2026-06-08T00:00:00.000Z'
'SNYK-JS-SHELLQUOTE-17457810':
- '* > shell-quote@1.8.4':
reason: 'Transitive dependency in @docusaurus/core via webpack-dev-server > launch-editor; fixed in shell-quote@1.9.0 but no direct upgrade path available. Dev-time only; not exploitable in current usage.'
expires: '2026-12-31T00:00:00.000Z'
created: '2026-06-25T00:00:00.000Z'
'SNYK-JS-IMAGESIZE-17295814':
- '* > image-size':
reason: 'Transitive dependency in @docusaurus/mdx-loader and dev build tooling; no upgrade or patch available from upstream. Not exploitable in current usage (build-time image dimension parsing only).'
expires: '2026-09-11T00:00:00.000Z'
created: '2026-06-11T00:00:00.000Z'
- '* > image-size@<=2.0.2':
reason: 'Transitive dependency in vitest@4.1.6; not exploitable in current usage.'
expires: '2026-07-11T00:00:00.000Z'
created: '2026-06-11T10:00:00.000Z'
'SNYK-JS-IMAGESIZE-17295816':
- '* > image-size':
reason: 'Transitive dependency in @docusaurus/mdx-loader and dev build tooling; no upgrade or patch available from upstream. Not exploitable in current usage (build-time image dimension parsing only).'
expires: '2026-09-11T00:00:00.000Z'
created: '2026-06-11T00:00:00.000Z'
- '* > image-size@<=2.0.2':
reason: 'Transitive dependency in vitest@4.1.6; not exploitable in current usage.'
expires: '2026-07-11T00:00:00.000Z'
created: '2026-06-11T10:00:00.000Z'
'SNYK-JS-AZUREIDENTITY-7964589':
- '* > @azure/identity@3.4.2':
reason: 'Transitive dependency via azurite>tedious; upgrade to 4.x is a breaking major-version change incompatible with azurite. Not exploitable in dev-only local storage emulation context.'
Expand Down Expand Up @@ -162,7 +129,7 @@ ignore:
'SNYK-JS-OPENTELEMETRYCORE-17373280':
- '* > @opentelemetry/core':
reason: 'The fix requires migrating the Azure Functions telemetry stack from OpenTelemetry 1.x to 2.8.0 or newer. The current Azure exporter and 0.57.x SDK packages require the 1.x API family; a forced major override is type-compatible at build time but leaves mixed SDK internals. Accepted temporarily while the existing OTEL 2.x migration is completed.'
expires: '2026-07-18T00:00:00.000Z'
expires: '2026-09-30T00:00:00.000Z'
created: '2026-06-18T00:00:00.000Z'
'SNYK-JS-BRACEEXPANSION-17706650':
- '* > brace-expansion@1.1.13':
Expand All @@ -171,6 +138,11 @@ ignore:
created: '2026-06-30T00:00:00.000Z'
'SNYK-JS-OPENTELEMETRYPROPAGATORJAEGER-17901201':
- '* > @opentelemetry/propagator-jaeger@<=1.30.1':
reason: 'The transitive dependency of @opentelemetry does not have a fixed upgrade path. Accepted temporarily until upgrade paths are made available.'
expires: '2026-07-18T00:00:00.000Z'
reason: 'The remaining 1.x OpenTelemetry SDK consumers cannot be upgraded independently without mixing incompatible SDK generations. The service-otel package requires a coordinated OTEL 2.x migration; the 2.9.0 override removes the vulnerable Jaeger package where compatible. Revisit when the migration is completed.'
expires: '2026-09-30T00:00:00.000Z'
created: '2026-06-18T00:00:00.000Z'
'SNYK-JS-REACTROUTER-18313151':
- '* > react-router@7.18.1':
reason: 'The advisory applies to React Router RSC/data-router action handling. This repository uses BrowserRouter, MemoryRouter, Routes, and Route only; it does not enable RSC mode or server actions. React Router 8.3.0, the first patched release, is not available in the configured registry. Revisit when the patched release is published and supported.'
expires: '2026-09-30T00:00:00.000Z'
created: '2026-07-30T00:00:00.000Z'
4 changes: 2 additions & 2 deletions apps/server-oauth2-mock/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { setupEnvironment } from './setup-environment.ts';

setupEnvironment();

const { PORT, BASE_URL } = process.env;
const { PORT, BASE_URL, PORTLESS_URL } = process.env;

const repoRoot = fileURLToPath(new URL('../../..', import.meta.url));
const appsDir = path.join(repoRoot, 'apps');
Expand All @@ -15,7 +15,7 @@ const port = Number.isFinite(rawPort) && rawPort > 0 ? rawPort : 1355;
// BASE_URL must be the externally-visible origin used as the OIDC issuer.
// In local dev the portless proxy handles TLS termination and host mapping.

let baseUrl = BASE_URL ?? `https://mock-auth.ownercommunity.localhost${port === 443 ? '' : `:${port}`}`;
let baseUrl = BASE_URL ?? PORTLESS_URL ?? `https://mock-auth.ownercommunity.localhost${port === 443 ? '' : `:${port}`}`;
// If BASE_URL was supplied but omits a port, ensure non-standard ports (like 1355) are preserved
baseUrl = ensurePortInUrl(baseUrl, port);

Expand Down
1 change: 1 addition & 0 deletions apps/ui-community/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"@storybook/react-vite": "catalog:",
"@types/react": "^19.1.8",
"@types/react-dom": "^19.1.6",
"autoprefixer": "^10.4.22",
"@vitejs/plugin-react": "^6.0.1",
"@vitest/coverage-istanbul": "catalog:",
"esbuild": "catalog:",
Expand Down
38 changes: 38 additions & 0 deletions build-pipeline/scripts/verify.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/usr/bin/env node
/// <reference types="node" />

import { architectureTests, coverageMerge, e2eTests, knipCheck, pnpmAudit, pnpmScript, snykCodeScan, snykDependencyScan, sonarPullRequestAnalysis, sonarQualityGate, verificationSequence } from '@cellix/local-dev/silent-runners';

const snykOrgArgs = ['--org=cellixjs', '--remote-repo-url=https://github.com/CellixJs/cellixjs'];
const snykDependencyArgs = [...snykOrgArgs, '--all-projects', '--policy-path=.snyk', '--exclude=dist,build,.turbo,coverage,.agents-work,.agents,.claude,.github,requirements.txt'];

const cellixVerify = verificationSequence
.addStep(pnpmScript('format:check'))
.addStep(architectureTests())
.addStep(coverageMerge())
.addStep(e2eTests())
.addStep(knipCheck())
.addStep(pnpmAudit({ auditLevel: 'high', dependencyType: 'prod', name: 'audit:prod' }))
.addStep(pnpmAudit({ auditLevel: 'critical', dependencyType: 'dev', name: 'audit:dev' }))
.addStep(
snykDependencyScan({
args: snykDependencyArgs,
}),
)
.addStep(
snykCodeScan({
args: snykOrgArgs,
}),
)
.addStep(sonarPullRequestAnalysis())
.addStep(sonarQualityGate());

function runVerifyCommand(): void {
const result = cellixVerify.run();
if (result.status === 0) {
process.stdout.write('verify passed\n');
}
process.exitCode = result.status;
}

runVerifyCommand();
7 changes: 6 additions & 1 deletion knip.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
{
"$schema": "https://unpkg.com/knip@5/schema.json",
"workspaces": {
".": {
"entry": ["build-pipeline/scripts/verify.ts"],
"project": ["build-pipeline/scripts/**/*.ts"]
},
"apps/api": {
"entry": ["src/index.ts", "start-*.ts", "sync-local-settings.ts", "rolldown.config.ts"],
"project": ["src/**/*.ts", "*.ts"],
Expand All @@ -9,7 +13,8 @@
"apps/ui-community": {
"entry": ["src/main.tsx", "start-dev.ts"],
"project": ["src/**/*.{ts,tsx}"],
"ignore": ["**/apollo-client-links.tsx"]
"ignore": ["**/apollo-client-links.tsx"],
"ignoreDependencies": ["autoprefixer"]
},
"apps/ui-staff": {
"entry": ["src/main.tsx", "start-dev.ts"],
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
"sonar:pr": "export PR_NUMBER=$(node build-pipeline/scripts/get-pr-number.cjs) && sonar-scanner -Dsonar.pullrequest.key=$PR_NUMBER -Dsonar.pullrequest.branch=$(git branch --show-current) -Dsonar.pullrequest.base=main",
"sonar:pr-windows": "for /f %i in ('node build-pipeline/scripts/get-pr-number.cjs') do set PR_NUMBER=%i && sonar-scanner -Dsonar.pullrequest.key=%PR_NUMBER% -Dsonar.pullrequest.branch=%BRANCH_NAME% -Dsonar.pullrequest.base=main",
"check-sonar": "node build-pipeline/scripts/check-sonar-quality-gate.cjs",
"verify": "pnpm run format:check && pnpm run test:arch && pnpm run test:coverage:merge && pnpm run test:e2e:worktree && pnpm run knip && pnpm run audit && pnpm run snyk",
"verify": "node --conditions=source build-pipeline/scripts/verify.ts",
"knip": "knip",
"snyk": "pnpm run snyk:test && pnpm run snyk:code",
"snyk:report": "pnpm run snyk:monitor && pnpm run snyk:code:report",
Expand All @@ -73,6 +73,7 @@
"@ant-design/cli": "^6.3.5",
"@biomejs/biome": "2.4.10",
"@cellix/graphql-codegen": "workspace:*",
"@cellix/local-dev": "workspace:*",
"@graphql-codegen/cli": "^5.0.7",
"@graphql-codegen/introspection": "^4.0.3",
"@graphql-codegen/typed-document-node": "^5.1.2",
Expand Down
98 changes: 90 additions & 8 deletions packages/cellix/local-dev/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# @cellix/local-dev

Generic local-development helpers for Cellix app wrappers.
Generic local-development and verification helpers for Cellix app wrappers.

This package is intentionally policy-free. It owns reusable mechanics such as worktree port math, URL helpers, JSON and dotenv utilities, process exit forwarding, and generic dev runners. App-specific env keys, hostnames, auth routes, and `local.settings.json` mutations belong in app-owned wrapper scripts or internal repo helpers, not here.
This package is intentionally policy-free. It owns reusable mechanics such as worktree port math, URL helpers, JSON and dotenv utilities, process exit forwarding, generic dev runners, and silent verification-command runners. App-specific env keys, hostnames, auth routes, scanner orgs, and `local.settings.json` mutations belong in app-owned wrapper scripts or internal repo helpers, not here.

## Install

Expand Down Expand Up @@ -30,6 +30,7 @@ In this monorepo, app packages consume the workspace package directly:
- Azure Functions
- Node-backed processes
- Azurite
- Silent verification command runners and portable tool-wrapper builders

## Recommended consumption pattern

Expand Down Expand Up @@ -109,6 +110,74 @@ values, including complete URL values nested in objects or arrays. It leaves URL
embedded in descriptive text unchanged. Use `convertSettingsForWorktree` when
the application needs explicit key-level conversion policy.

## Silent runners

`runSilentCommand` captures stdout and stderr while a command is running. If the
command succeeds, nothing is printed. If it fails, whatever the command wrote to
stdout and stderr is replayed before the failing status is returned.

```js
import { runSilentCommand } from '@cellix/local-dev/silent-runners';

const result = runSilentCommand({
command: 'snyk',
args: ['test', '--all-projects'],
});

process.exitCode = result.status;
```

`result.status` is always a number, so it can be assigned straight to
`process.exitCode`. A command terminated by a signal has no exit status of its
own and is mapped to the shell convention of `128 + signalNumber` (SIGINT
becomes 130, SIGKILL becomes 137); its replayed header names the signal rather
than an exit code, and `result.signal` carries the signal itself.

Use `runSilentCommandSequence` when a wrapper needs to run several commands in
order. Steps are silent by default; mark a step with `output: 'inherit'` only
when its live output is part of the intended consumer experience.

```js
import { runSilentCommandSequence } from '@cellix/local-dev/silent-runners';

const result = runSilentCommandSequence({
steps: [
{ name: 'format:check', command: 'pnpm', args: ['run', 'format:check'] },
{ name: 'test:e2e', command: 'pnpm', args: ['run', 'test:e2e'] },
],
});

process.exitCode = result.status;
```

For reusable verification workflows, use the fluent sequence builder:

```js
import { pnpmScript, verificationSequence } from '@cellix/local-dev/silent-runners';

const verify = verificationSequence
.addStep(pnpmScript('format:check'))
.addStep(pnpmScript('test'));

const result = verify.run();
process.exitCode = result.status;
```

Prefer the named tool wrappers when a command has a known CLI shape:

```js
import { knipCheck, pnpmAudit, runSilentCommandSequence, snykCodeScan, snykDependencyScan } from '@cellix/local-dev/silent-runners';

const result = runSilentCommandSequence({
steps: [
knipCheck(),
pnpmAudit({ auditLevel: 'high', dependencyType: 'prod' }),
snykDependencyScan({ args: ['--all-projects', '--org=my-org'] }),
snykCodeScan({ args: ['--org=my-org'] }),
],
});
```

## Public API

All exports are available from `@cellix/local-dev`. Folder-level subpaths are
Expand All @@ -117,6 +186,7 @@ also published for consumers that want narrower imports:
- `@cellix/local-dev/files`
- `@cellix/local-dev/process`
- `@cellix/local-dev/runners`
- `@cellix/local-dev/silent-runners`
- `@cellix/local-dev/urls`
- `@cellix/local-dev/vite`
- `@cellix/local-dev/workspace`
Expand Down Expand Up @@ -152,15 +222,27 @@ also published for consumers that want narrower imports:
- `getMongoPort`
- `getAzuritePorts`
- `buildAzuriteConnectionString`
- `runViteDev`
- `runDocusaurusDev`
- `runAzureFunctionsDev`
- `runNodeDev`
- `runAzuriteDev`
- `runTsxDev` deprecated compatibility alias
- `runSilentCommand`
- `runSilentCommandSequence`
- `architectureTests`
- `coverageMerge`
- `e2eTests`
- `knipCheck`
- `livePnpmScript`
- `pnpmAudit`
- `pnpmScript`
- `snykCodeScan`
- `snykDependencyScan`
- `snykIacScan`
- `sonarPullRequestAnalysis`
- `sonarQualityGate`
- `VerificationSequence`
- `verificationSequence`

## Notes

- The package derives workspace roots from the caller's current working directory, but it does not infer app layouts or env-variable names.
- Worktree names are sanitized before they are inserted into `.localhost` hostnames so branch-style names such as `jason/my-feature` become DNS-safe labels such as `jason-my-feature`. Suffixing is idempotent for hostnames that already contain the sanitized worktree label.
- Silent tool wrappers encode reusable CLI shape; scripts still own project-specific arguments such as org names, paths, and CI policy.
- Captured verification output defaults to 64 MiB and can be adjusted with `maxBuffer` for a command, sequence, or individual sequence step.
- If a helper only exists to support one app's local policy, it should usually live with that app instead of being exported here.
Loading
Loading