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
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @danfry1
38 changes: 38 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
version: 2
updates:
- package-ecosystem: bun
directory: /
schedule:
interval: weekly
day: monday
open-pull-requests-limit: 10
# Supply-chain hardening: hold update PRs until a version has been public for
# at least seven days, long enough for most malicious releases to be yanked.
# Mirrors the install-time minimumReleaseAge gate in bunfig.toml.
cooldown:
default-days: 7
semver-major-days: 7
semver-minor-days: 7
semver-patch-days: 7
ignore:
# Keep @types/node on the major matching the lowest supported engines.node
# (>=18). A higher major would let the type-checker accept Node APIs newer
# than our floor.
- dependency-name: "@types/node"
update-types: ["version-update:semver-major"]
groups:
dev-dependencies:
dependency-type: development
update-types: [minor, patch]
production-dependencies:
dependency-type: production
update-types: [minor, patch]

- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
day: monday
open-pull-requests-limit: 5
cooldown:
default-days: 7
14 changes: 9 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@ on:
pull_request:
branches: [main]

permissions: read-all

jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
- run: bun install --frozen-lockfile
- name: Verify dependencies are pinned
run: bun run lint:deps
- run: bun run lint
- run: bun run typecheck
- run: bun run test # enforces the coverage gate in packages/faultline/bunfig.toml
Expand All @@ -30,12 +34,12 @@ jobs:
matrix:
node-version: [18, 20, 22]
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
- run: bun install --frozen-lockfile
- name: Build publishable packages
run: bun --filter 'faultline' --filter 'eslint-plugin-faultline' --filter 'faultline-cli' build
- uses: actions/setup-node@v4
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: ${{ matrix.node-version }}
- name: Smoke-test built artifacts on Node ${{ matrix.node-version }}
Expand Down
18 changes: 18 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: CodeQL

on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: '0 6 * * 1' # Monday 6am UTC

permissions: read-all

jobs:
codeql:
permissions:
security-events: write
contents: read
uses: danfry1/standards/.github/workflows/codeql.yml@v1
24 changes: 15 additions & 9 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,34 @@ name: Deploy to GitHub Pages
on:
push:
branches: [main]
paths:
- 'website/**'
- '.github/workflows/pages.yml'
workflow_dispatch:

permissions:
contents: read
pages: write
id-token: write
permissions: read-all

concurrency:
group: pages
cancel-in-progress: true

jobs:
deploy:
runs-on: ubuntu-latest
timeout-minutes: 10

permissions:
pages: write
id-token: write

environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/configure-pages@v5
- uses: actions/upload-pages-artifact@v3
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
- uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
with:
path: website
- id: deployment
uses: actions/deploy-pages@v4
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
9 changes: 5 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,15 @@ jobs:
runs-on: ubuntu-latest
environment: npm
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- uses: actions/setup-node@v4
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 22
registry-url: https://registry.npmjs.org
- run: npm i -g npm@latest
- run: bun install --frozen-lockfile
- run: bun run lint:deps
- run: bun run typecheck
- run: bun run test
- name: Validate package exports (faultline)
Expand All @@ -36,7 +37,7 @@ jobs:
npm pack
npx @arethetypeswrong/cli ./faultline-*.tgz --ignore-rules no-resolution
- name: Create Release PR or Publish
uses: changesets/action@v1
uses: changesets/action@a45c4d594aa4e2c509dc14a9f2b3b67ba3780d0d # v1
with:
version: bun run version-packages
publish: bun run release
Expand Down
17 changes: 17 additions & 0 deletions .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: OpenSSF Scorecard

on:
push:
branches: [main]
schedule:
- cron: '0 6 * * 1' # Monday 6am UTC
workflow_dispatch:

permissions: read-all

jobs:
scorecard:
permissions:
security-events: write
id-token: write
uses: danfry1/standards/.github/workflows/scorecard.yml@v1
21 changes: 21 additions & 0 deletions .syncpackrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"versionGroups": [
{
"label": "Peer deps intentionally use wide ranges; dev pins the version we test against, so cross-instance version differences are expected.",
"dependencies": ["eslint", "typescript", "@typescript-eslint/utils"],
"isIgnored": true
}
],
"semverGroups": [
{
"label": "devDependencies are pinned to exact versions (supply-chain hardening)",
"dependencyTypes": ["dev"],
"range": ""
},
{
"label": "runtime + peer deps keep author-defined ranges so consumers can dedupe",
"dependencyTypes": ["prod", "peer"],
"isIgnored": true
}
]
}
11 changes: 11 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,17 @@ bun run build # build all packages

Per-package: `bun --filter '<package-name>' <script>`.

## Dependencies

`devDependencies` are pinned to exact versions (supply-chain hardening) and enforced by [syncpack](https://github.com/JamieMason/syncpack):

```bash
bun run lint:deps # fails if a dev dependency isn't pinned (also runs in CI)
bun run fix:deps # auto-pin / reconcile versions
```

After adding or bumping a dependency, run `bun run fix:deps` and commit the result. Runtime and peer dependencies intentionally keep ranges. Note that installs are subject to a 7-day `minimumReleaseAge` gate (`bunfig.toml`), so a just-published version may be refused until it ages in — see [SECURITY.md](./SECURITY.md#supply-chain-hardening).

## Tests

- Use Bun's test runner (`bun:test`).
Expand Down
14 changes: 14 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,18 @@ faultline is a TypeScript error-handling library with **zero runtime dependencie
- **Serialization / redaction** (`serializeError`, `configureErrors` redaction paths) — ensuring error payloads don't leak sensitive data. Note that `redactPaths` matches against the *serialized error structure* and a non-matching path is a silent no-op (it fails open). For sensitive keys, prefer the globstar form `**.password`, which redacts the key at any depth. If you find a way correctly-configured redaction can be bypassed, that's in scope.
- **Deserialization** of untrusted serialized errors.

## Supply-chain hardening

This repo follows my cross-project baseline, documented in full (with rationale) at
[danfry1/standards → supply-chain.md](https://github.com/danfry1/standards/blob/main/supply-chain.md).
In short, it applies defense-in-depth against dependency-based supply-chain attacks:

- **Install-time release-age gate.** `bunfig.toml` sets `minimumReleaseAge` to 7 days, so installs refuse npm versions published more recently than that — long enough for most malicious releases to be caught and yanked.
- **Update cooldown.** Dependabot (`.github/dependabot.yml`) holds update PRs until a version is at least 7 days old (all semver levels), mirroring the install-time gate.
- **Pinned dependencies.** All `devDependencies` are pinned to exact versions (no `^`/`~`), enforced in CI by [syncpack](https://github.com/JamieMason/syncpack) (`bun run lint:deps`). Runtime/peer deps keep author-defined ranges so consumers can dedupe. The committed `bun.lock` pins the full tree for reproducible installs.
- **Pinned GitHub Actions.** Every action is pinned to a full commit SHA (with a version comment), so a compromised or moved tag can't inject code into CI.
- **Least-privilege CI.** Workflows default to `permissions: read-all`; write scopes are granted only to the specific jobs that need them.
- **Provenance.** Publishes use npm provenance (`--provenance` via `NPM_CONFIG_PROVENANCE`) so released artifacts are cryptographically linked to the building workflow.
- **Automated scanning.** CodeQL (`codeql.yml`) and OpenSSF Scorecard (`scorecard.yml`) run on push and weekly.

Thanks for helping keep faultline and its users safe.
Loading