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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .changeset/secure-v5-release-readiness.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
'@cleverbrush/async': major
'@cleverbrush/auth': major
'@cleverbrush/client': major
'@cleverbrush/deep': major
'@cleverbrush/di': major
'@cleverbrush/env': major
'@cleverbrush/knex-clickhouse': major
'@cleverbrush/knex-schema': major
'@cleverbrush/log': major
'@cleverbrush/mapper': major
'@cleverbrush/orm': major
'@cleverbrush/orm-cli': major
'@cleverbrush/otel': major
'@cleverbrush/react-form': major
'@cleverbrush/scheduler': major
'@cleverbrush/scheduler-postgres': major
'@cleverbrush/schema': major
'@cleverbrush/schema-json': major
'@cleverbrush/server': major
'@cleverbrush/server-openapi': major
'@cleverbrush/storage': major
'@cleverbrush/storage-s3': major
---

Require Node.js 24+ consistently across all published packages. Correct the root and all published-package license files to BSD-3-Clause, matching package metadata and documentation, and verify license consistency in source and npm tarballs. See docs/MIGRATION-v5.md for migration guidance.

Harden JWT key/algorithm and claim validation, cookie parsing/serialization, and request-body lifecycle handling. Require explicit authorization scope for bounded server idempotency; coalesce concurrent retries and capture full response bodies. Bound response caching and bypass private, no-store and cookie-setting responses.

Preserve DI scope validation through factories and propagate registered optional-service failures. Fix batch response status/header capture, timeout abort-listener cleanup, concurrent deduplication response cloning, CLI database cleanup on validation/production-guard failures, and the missing client idempotency JavaScript export. Update security-sensitive dependencies and ensure OpenTelemetry disable flags override SDK defaults.

Add regression tests, package-consumer smoke checks, package-level unit coverage floors, migration/security documentation and release validation gates.
62 changes: 59 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
name: CI

on:
push:
branches: [master]
pull_request:
workflow_call:

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
group: framework-validation-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
Expand Down Expand Up @@ -44,6 +46,27 @@ jobs:
- name: Test & Typecheck
run: npm run test

- name: Coverage and package floors
run: npm run test:coverage

- name: Dependency security
run: npm audit --audit-level=high

- name: Packed package smoke tests
run: npm run test:packages

- name: Build documentation websites
run: npm run build:schema-site && npm run build:docs-site

- name: Generate every package API reference
run: npx typedoc --out "$RUNNER_TEMP/framework-api-docs"

- uses: actions/upload-artifact@v4
if: always()
with:
name: coverage-node-${{ matrix.node }}
path: coverage/

query-integration:
name: PostgreSQL Query Integration
runs-on: ubuntu-latest
Expand Down Expand Up @@ -74,6 +97,9 @@ jobs:
- run: npm run build
- run: npm run test:queries:integration
- run: npm run test:scheduler:integration
- run: npm run test:queries:integration && npm run test:scheduler:integration
env:
TZ: America/Los_Angeles
- run: node demos/durable-jobs/demo.ts
- run: node demos/durable-jobs/periodic.ts --fast

Expand All @@ -89,3 +115,33 @@ jobs:
- run: npm ci
- run: npm run build
- run: npm run test:storage:integration

demo-e2e:
name: Demo API, browser and telemetry E2E
runs-on: ubuntu-latest
timeout-minutes: 30
env:
CI: 'true'
KEEP_STACK: '0'
COMPOSE_PROJECT_NAME: framework-e2e
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: npm
- run: npm ci
- run: npm run build
- run: npm run playwright:install --workspace @cleverbrush/demo-e2e -- --with-deps
- run: npm run test:e2e
- name: Collect isolated stack logs
if: failure()
run: docker compose -f demos/docker-compose.yml logs --no-color > e2e-stack.log
- uses: actions/upload-artifact@v4
if: failure()
with:
name: demo-e2e-logs
path: e2e-stack.log
- name: Remove disposable CI stack
if: always()
run: docker compose -f demos/docker-compose.yml down --volumes --remove-orphans
4 changes: 4 additions & 0 deletions .github/workflows/publish-beta.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ permissions:
contents: read

jobs:
validate:
uses: ./.github/workflows/ci.yml

publish-beta:
needs: validate
name: Publish Beta to npm
runs-on: ubuntu-latest

Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@ permissions:
pull-requests: write

jobs:
validate:
permissions:
contents: read
uses: ./.github/workflows/ci.yml

release:
needs: validate
name: Version & Publish
runs-on: ubuntu-latest

Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
22
24
10 changes: 6 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ npm run lint:fix

| Property | Value |
|---|---|
| Package manager | npm (v24+) |
| Package manager | npm 11 (see `packageManager`) |
| Build system | Turborepo (`turbo run build`) |
| Language | TypeScript — target ES2022, `moduleResolution: bundler` |
| Lint / Format | [Biome](https://biomejs.dev) (not ESLint or Prettier) |
| Test runner | [Vitest](https://vitest.dev) (with built-in typecheck) |
| Node.js | 20+ (22 recommended — see `.nvmrc`) |
| Node.js | 24+ (see `.nvmrc`) |
| Module system | ES Modules (`"type": "module"` in root `package.json`) |

### Workspace layout
Expand Down Expand Up @@ -73,6 +73,8 @@ scripts/ ← build/release helper scripts
| `@cleverbrush/otel` | OpenTelemetry instrumentation |
| `@cleverbrush/env` | Environment-variable parsing with schema validation |
| `@cleverbrush/schema-json` | JSON Schema generation from schema builders |
| `@cleverbrush/storage` | Provider-neutral object storage contracts |
| `@cleverbrush/storage-s3` | Streaming S3-compatible storage |

---

Expand Down Expand Up @@ -152,8 +154,8 @@ The `demos/` directory is linted separately (see `demos/todo-backend/biome.json`
## Testing Conventions

- Tests are **co-located** with source files: `src/foo.ts` → `src/foo.test.ts`
- Vitest globals are available (`describe`, `it`, `expect`, etc.) — no explicit
import needed (configured via `"types": ["vitest/globals"]` in `tsconfig.json`)
- Import runtime helpers (`describe`, `it`, `expect`, etc.) from `vitest`.
Ambient TypeScript declarations do not enable runtime globals.
- Run with `npm run test` which also performs TypeScript typechecking
- Benchmarks live in `libs/benchmarks/` and run with `npm run bench`
- Server integration tests live in `libs/server-integration-tests/`
Expand Down
57 changes: 51 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Thanks for your interest in contributing! This guide will help you get started.

## Prerequisites

- **Node.js** 20 or later (22 recommended — see `.nvmrc`)
- **npm** (ships with Node)
- **Node.js** 24 or later (see `.nvmrc`)
- **npm** 11 (see the root `packageManager` field)

## Getting Started

Expand All @@ -24,6 +24,47 @@ npm run build
npm run test
```

The root build also refreshes workspace CLI links. On a fresh checkout npm cannot
link `cb-orm` until its generated `dist/bin.js` exists; the postbuild step makes
demo migration commands work without a second dependency installation.

## Release verification

In addition to lint, build and unit/type tests, CI runs:

```bash
npm run test:coverage
npm run test:packages
npm audit --audit-level=high
npm run typecheck:schema-site
npm run typecheck:docs-site
npm run build:schema-site
npm run build:docs-site
```

`coverage-thresholds.json` sets per-package statement, branch, function and line
floors for **unit** coverage. New published packages need explicit floors; do not
lower existing floors to hide regressions. Refresh README badges explicitly with
`npm run coverage:badges` after a successful coverage run. Badges do not include
the dedicated database or S3 integration suites. In particular,
`scheduler-postgres` relies on the real-database suite, not its small unit suite.

The package smoke test packs every published workspace, installs the tarballs
and peer dependencies in a disposable consumer, checks every export and TypeScript
declaration, and bundles browser entry points without Node polyfills. It requires
registry access and deletes only its own temporary directory on completion.

CI runs the query and durable scheduler integration suites against disposable
PostgreSQL in UTC and America/Los_Angeles, and the storage suite against Garage.
Locally, provide isolated `QUERY_TEST_DATABASE_URL` and
`SCHEDULER_TEST_DATABASE_URL` values, then run `npm run test:queries:integration`
and `npm run test:scheduler:integration`. `npm run test:storage:integration`
creates and cleans up its own Docker service. Never point tests at production.
The full demo API/browser/telemetry E2E stack and API-reference generation also
run in CI. Both beta and stable publication wait for this reusable validation
workflow. TypeDoc's non-exported internal-type warnings remain visible; they are
not suppressed by the documentation build.

## Monorepo Structure

This project uses **npm workspaces** with **Turborepo** for orchestration. All packages live under `libs/`:
Expand All @@ -35,9 +76,12 @@ This project uses **npm workspaces** with **Turborepo** for orchestration. All p
| `@cleverbrush/async` | Async utilities (Collector, debounce, throttle, retry) |
| `@cleverbrush/mapper` | Schema-driven object mapping |
| `@cleverbrush/react-form` | React form library powered by schema PropertyDescriptors |
| `@cleverbrush/scheduler` | Cron-like job scheduler with schema-validated config |
| `@cleverbrush/scheduler` | Typed durable jobs, recurring schedules and progress |
| `@cleverbrush/knex-clickhouse` | Knex dialect for ClickHouse |

This table highlights foundational packages. The [root package inventory](README.md#packages)
lists all published packages, including HTTP, persistence, storage and telemetry.

## Development Workflow

### Code Style
Expand Down Expand Up @@ -79,11 +123,12 @@ npm run clean
The extension system is the primary way to add new validators. See `libs/schema/src/extensions/` for examples.

1. Create your extension file (e.g. `libs/schema/src/extensions/myExtension.ts`)
2. Export extension functions that call the builder's `.extend()` method
2. Define methods with `defineExtension()` and return the new immutable builder
3. Add tests in a co-located `*.test.ts` file
4. Re-export from `libs/schema/src/extensions/index.ts`

Look at `libs/schema/src/extensions/string.ts` for a complete example of how extensions add validators like `email()`, `url()`, `uuid()`, etc.
See the schema README's extension-system examples for `defineExtension()` and
`withExtensions()`. Do not discard the builder returned by an extension method.

## Adding a New Builder

Expand All @@ -97,7 +142,7 @@ Builders live in `libs/schema/src/builders/`. Each builder extends the base `Sch

## Pull Request Process

1. **Fork** the repo and create a feature branch from `master`
1. Create a feature branch from `development` and target `development` in the PR
2. Make your changes with tests
3. **Add a changeset** — every PR that changes package behavior needs one:
```bash
Expand Down
80 changes: 28 additions & 52 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,52 +1,28 @@
Cleverbrush Framework is dual-licensed under both the "Unlicense" and the
"Zero-Clause BSD" (0BSD) licenses. The intent of this dual-licensing
structure is to make Cleverbrush Framework as consumable as possible in as many
environments / countries / companies as possible without encumbering
users.

This license applies to all of the Cleverbrush Framework source code, build code,
and tests.

The text of the two licenses follows below:

============================== UNLICENSE ==============================

This is free and unencumbered software released into the public domain.

Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.

In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

For more information, please refer to <http://unlicense.org>

================================ 0BSD =================================

Copyright (C) 2024 by Andrew Zolotuhkin <andrew_zol@cleverbrush.com>

Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
BSD 3-Clause License

Copyright (C) 2024 by Andrew Zolotuhkin <andrew_zol@cleverbrush.com>

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Loading
Loading