Skip to content

test: add fast-check for OpenSSF Scorecard Fuzzing check - #231

Merged
rhuanbarreto merged 1 commit into
mainfrom
fix/scorecard-env
Apr 26, 2026
Merged

test: add fast-check for OpenSSF Scorecard Fuzzing check#231
rhuanbarreto merged 1 commit into
mainfrom
fix/scorecard-env

Conversation

@rhuanbarreto

Copy link
Copy Markdown
Contributor

Summary

  • Replace hand-rolled random generators in fuzz tests with fast-check, a property-based testing library that OpenSSF Scorecard recognizes as a JavaScript/TypeScript fuzzing framework
  • The Scorecard Fuzzing check scans .ts files for import ... from 'fast-check' — this addresses the 0/10 Fuzzing score
  • Test coverage is equivalent: parseFrontmatter, parseAdr, AdrFrontmatterSchema, DomainNameSchema, DomainPrefixSchema, and ProjectConfigSchema exercised with 500 runs each

Expected Scorecard Impact

Check Before After
Fuzzing 0/10 10/10

Test plan

  • bun run validate passes (690 tests, 22/22 ADR rules)
  • 22 fuzz tests pass with 5,930 assertions
  • After merge: re-run Scorecard and verify Fuzzing score improves

Replace hand-rolled random generators with fast-check, a
property-based testing library that the OpenSSF Scorecard
recognizes as a fuzzing framework for JavaScript/TypeScript.

The scorecard Fuzzing check scans .ts files for fast-check
imports — this addresses the 0/10 Fuzzing score.

Test coverage is equivalent: parseFrontmatter, parseAdr,
AdrFrontmatterSchema, DomainNameSchema, DomainPrefixSchema,
and ProjectConfigSchema are all exercised with 500 runs each
using fc.property() arbitraries.
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Apr 26, 2026

Copy link
Copy Markdown

Deploying archgate-cli with  Cloudflare Pages  Cloudflare Pages

Latest commit: ab60138
Status: ✅  Deploy successful!
Preview URL: https://67ea06b7.archgate-cli.pages.dev
Branch Preview URL: https://fix-scorecard-env.archgate-cli.pages.dev

View logs

@rhuanbarreto
rhuanbarreto merged commit df28062 into main Apr 26, 2026
10 checks passed
@rhuanbarreto
rhuanbarreto deleted the fix/scorecard-env branch April 26, 2026 18:03
rhuanbarreto added a commit that referenced this pull request Jul 26, 2026
…ity (#523)

Closes #516.

## The gap was live, not hypothetical

GEN-002 has always required correct diacritics — *"DO use correct
diacritical marks in Portuguese — `não` not `nao`, `código` not
`codigo`"* — but nothing enforced it. The companion rules checked only
**structure**: page parity, translation drift, link prefixes. So six
`pt-br` pages sat in `main` with their diacritics stripped, plus a
seventh with a corrupted frontmatter `description`.

`nb` hit the identical failure in #384: ~500 occurrences across 35
files, fixed in two manual passes, where the second pass caught four
cases the first missed. Manual review is not a reliable detector for
this.

## Content

Diacritics restored across seven `pt-br/examples` pages — prose,
headings, and frontmatter descriptions. Verified mechanically: **0
stripped forms remain**, and **fenced code blocks are byte-identical to
`main` in all seven files**, so no identifier, command, or path was
touched.

## Rules

Two additions to `GEN-002-docs-i18n.rules.ts`, both `error`:

- **`i18n-encoding-corruption`** — accented characters written as HTML
entities (`å`, `ç`) or as double-encoded UTF-8. Detection
requires a `0xC2`/`0xC3` lead byte **followed by** a `0x80`–`0xBF`
continuation byte. A bare lead-byte scan would flag legitimate uppercase
Portuguese, where `Ã` precedes an ASCII letter — `ÃO` already occurs
twice in this tree.
- **`i18n-diacritic-density`** — accented characters per 1000 prose
letters per locale, ignoring fenced and inline code.

Thresholds come from measuring the corpus, not from taste:

| | healthy minimum | stripped pages | threshold |
|---|---|---|---|
| `nb` | 5.9 / 1000 | — | 2 |
| `pt-br` | 15.2 / 1000 | 0.0–1.1 | 5 |

**A whole-file "has at least one diacritic" check was tried and
rejected.** Measured against the six corrupt files it caught **one**:
`wrapper-enforcement.mdx` was fully stripped in prose but contained
`Não` inside a code sample, which defeats it. Density caught five of
six, with a 14× gap between the bands.

Accented characters in the rules file are numeric code-point sets, never
literals, so the check cannot be broken by the corruption it detects.

## Documented limits

`i18n-diacritic-density` is a bulk-stripping detector, not a spell
checker. It does **not** catch isolated stripped words in
otherwise-correct prose — `max-file-length.mdx` scored a healthy 26.6
while its frontmatter was stripped, and only a word-level scan found it
— and it skips pages under 200 prose letters. Both limits are written
into GEN-002's Compliance section as review responsibilities rather than
left implicit.

## Verification

`bun run validate` green: 1675 tests, 49/49 rules, build clean.
Fire-tested both directions:

| Case | Result |
|---|---|
| Stripped page restored from `main` | density rule fires, names the
file |
| `å` injected | caught, correct line |
| Double-encoded `ø` injected | caught, correct line |
| `VALIDAÇÃO COMPLETA` in `pt-br` | not flagged |

## Review request

**Please read the Portuguese as a native speaker.** The automated checks
count accents; they cannot tell a correct accent from a confidently
wrong one. `à` versus `a` (crasis) and `é` versus `e` are the places to
look — I added several of each. An orthography review agent returned
PASS here, but its per-word annotations were fabricated, so its verdict
carries no weight.

---------

Signed-off-by: Rhuan Barreto <rhuan@barreto.work>
@archgatebot archgatebot Bot mentioned this pull request Jul 26, 2026
rhuanbarreto pushed a commit that referenced this pull request Jul 26, 2026
# archgate

## [0.51.0](v0.50.0...v0.51.0)
(2026-07-26)

### Features

* **adrs:** enforce concise, forward-only code comments (GEN-004)
([#496](#496))
([9a114b3](9a114b3)),
references [#2123](https://github.com/archgate/cli/issues/2123)
* **adrs:** flag stray files at the repository root (GEN-005)
([#535](#535))
([6a6e765](6a6e765)),
closes [#514](#514), references
[#500](#500)
* **engine:** add ctx.readYAML and ctx.checkCase rule helpers
([#497](#497))
([c5d82c5](c5d82c5)),
closes [#490](#490), references
[#490](#490)
[#491](#491)
[#499](#499)
[#499](#499)
[#499](#499)
[#499](#499)
* report truncated ADR briefings, trim the ADR corpus 15.6%, add GEN-005
briefing budget ([#501](#501))
([a9dab40](a9dab40))

### Bug Fixes

* **docs:** relocate ADR content to clear briefing-budget warnings
([#531](#531))
([c7419b3](c7419b3))
* **docs:** restore pt-br diacritics and enforce locale content
integrity ([#523](#523))
([db39104](db39104)),
closes [#516](#516), references
[#231](#231)
* **engine:** allow symlinks that resolve inside the project root
([#500](#500))
([387bf15](387bf15))
* **engine:** reject rule-file reads through a symlinked ancestor
directory ([#499](#499))
([a555f9d](a555f9d)),
references [#497](#497)
[#491](#491)
[#497](#497)
[#497](#497)
[#497](#497)
[#497](#497)
* **engine:** scan top-level export declarations with a null source
([#493](#493))
([d07db03](d07db03)),
closes [#491](#491)
* **engine:** stop dropping AST nodes with exotic literal values
([#494](#494))
([0015542](0015542)),
closes [#493](#493)
[#493](#493)
* **lint:** resolve no-bare-env-restore by captured key and lexical
scope ([#524](#524))
([7094a3a](7094a3a)),
closes [#498](#498)
* **rules:** make ARCH-020 and ARCH-023 match ctx.ast() instead of raw
text ([#533](#533))
([ad5529b](ad5529b)),
closes [#513](#513), references
[#486](#486)
* **tests:** replace bun:test anti-patterns with idiomatic patterns
([#512](#512))
([bcb086f](bcb086f))

---
This PR was generated with
[simple-release](https://github.com/TrigenSoftware/simple-release).

<details>
<summary>📄 Cheatsheet</summary>
<br>



You can configure the bot's behavior through a pull request comment
using the `!simple-release/set-options` command.

### Command Format

````md
!simple-release/set-options

```json
{
  "bump": {},
  "publish": {}
}
```
````

### Useful Parameters

#### Bump

| Parameter | Type | Description |
|-----------|------|-------------|
| `version` | `string` | Force set specific version |
| `as` | `'major' \| 'minor' \| 'patch' \| 'prerelease'` | Release type
|
| `prerelease` | `string` | Pre-release identifier (e.g., "alpha",
"beta") |
| `firstRelease` | `boolean` | Whether this is the first release |
| `skip` | `boolean` | Skip version bump |
| `byProject` | `Record<string, object>` | Per-project bump options for
monorepos |

#### Publish

| Parameter | Type | Description |
|-----------|------|-------------|
| `skip` | `boolean` | Skip publishing |
| `access` | `'public' \| 'restricted'` | Package access level |
| `tag` | `string` | Tag for npm publication |

### Usage Examples

#### Force specific version

````md
!simple-release/set-options

```json
{
  "bump": {
    "version": "2.0.0"
  }
}
```
````

#### Force major bump

````md
!simple-release/set-options

```json
{
  "bump": {
    "as": "major"
  }
}
```
````

#### Create alpha pre-release

````md
!simple-release/set-options

```json
{
  "bump": {
    "prerelease": "alpha"
  }
}
```
````

#### Publish with specific access and tag

````md
!simple-release/set-options

```json
{
  "bump": {
    "prerelease": "beta"
  },
  "publish": {
    "access": "public",
    "tag": "beta"
  }
}
```
````

### Custom Changelog Preamble

You can add custom markdown to the top of the changelog (right after the
version header) using the `!simple-release/set-preamble` command. The
markdown after the command line becomes the preamble.

```md
!simple-release/set-preamble

## What's new?

- The website was completely redesigned
- The new API gives you awesome possibilities
```

In a monorepo, pass the full package name after the command to target a
single package's changelog. Wrap the name in backticks so GitHub keeps
it as text instead of a mention:

```md
!simple-release/set-preamble `@your-org/core`

## Core changes

- New plugin system
```

Use one comment per package, plus one without a name for the whole
release.

### Access Restrictions

The commands can only be used by users with permissions:
- repository owner
- organization member
- collaborator

### Notes

- The last comment with `!simple-release/set-options` command takes
priority
- The last `!simple-release/set-preamble` comment per package takes
priority
- JSON must be valid, otherwise the `set-options` command will be
ignored
- Parameters apply only to the current release execution
- The commands can be updated by editing the comment or adding a new one


</details>

<!--
  Please do not edit this comment.
  simple-release-pull-request: true
  simple-release-branch-from: release
  simple-release-branch-to: main
-->

Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
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