From d8032b69512dca01ef7d6d4f59605a70fc7431a3 Mon Sep 17 00:00:00 2001 From: Bryan Fawcett Date: Sat, 12 Sep 2026 02:41:58 +0800 Subject: [PATCH] ci(lint): adopt the canonical org lint gate Adds the identical caller every repo in the seven orgs now uses, and the canonical .prettierrc, .prettierignore, .markdownlint.jsonc, .yamllint.yaml and .editorconfig from nyuchi/.github. No copy of the lint policy is added here. This org's .github repo keeps its own reusables (gitleaks, rust-ci, pr-title-lint) but the LINT policy stays in exactly one place: nyuchi/.github is public, and a public reusable workflow is callable from any org, so all seven orgs call the one file. Five divergent copies is the failure this is undoing. Fixes one real markdown bug found by the gate: in ORG_STANDARDS.md a line wrapped so that "# 265" began a line, which every markdown renderer reads as an H1. It is now an inline code span on the previous line. Co-Authored-By: Claude Opus 5 (1M context) --- .editorconfig | 40 ++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 4 +- .github/workflows/lint.yml | 38 ++++++++++ .markdownlint.jsonc | 39 ++++++++++ .prettierignore | 30 ++++++++ .prettierrc | 16 ++++ .yamllint.yaml | 57 ++++++++++++++ CODE_OF_CONDUCT.md | 24 +++--- CONTRIBUTING.md | 2 +- ORG_STANDARDS.md | 126 +++++++++++++++---------------- README.md | 32 ++++---- SECURITY.md | 34 ++++----- SUPPORT.md | 34 ++++----- 13 files changed, 347 insertions(+), 129 deletions(-) create mode 100644 .editorconfig create mode 100644 .github/workflows/lint.yml create mode 100644 .markdownlint.jsonc create mode 100644 .prettierignore create mode 100644 .prettierrc create mode 100644 .yamllint.yaml diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..f4c7245 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,40 @@ +# EditorConfig — https://editorconfig.org +# Keeps whitespace consistent across editors and IDEs before +# Prettier / rustfmt / ruff get a chance to run. + +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +indent_size = 2 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +# Markdown: trailing spaces are significant (hard line-break). +# Let Prettier handle wrapping; don't trim here. +trim_trailing_whitespace = false + +[*.{yml,yaml}] +indent_size = 2 + +[*.{json,jsonc}] +indent_size = 2 + +[*.toml] +indent_size = 4 + +[Makefile] +indent_style = tab + +[*.rs] +# rustfmt handles Rust formatting; EditorConfig just sets the baseline. +indent_size = 4 + +[*.py] +indent_size = 4 + +[*.{cpp,cc,c,h,hpp}] +indent_size = 4 diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 0f91920..d3bfbae 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -16,8 +16,8 @@ ## Commits -- [ ] Each commit is a coherent step with a message that says *why*, not - just *what*. They are not going to be squashed away. +- [ ] Each commit is a coherent step with a message that says _why_, not + just _what_. They are not going to be squashed away. - [ ] No "fix typo" / "address review" commits left in the history — fold them into the commit they belong to before requesting review. diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..f766bb6 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,38 @@ +# The org-wide lint gate. Drop this file in as +# .github/workflows/lint.yml and change nothing else. +# +# The five checks it publishes are exactly the five contexts the +# org ruleset requires: +# +# lint / actionlint +# lint / JSON validity +# lint / prettier +# lint / markdownlint +# lint / yamllint +# +# Those strings come from the job being called `lint` and calling a +# reusable workflow - a check publishes as " / ". +# Do NOT convert this to a matrix: a matrix publishes +# "lint (actionlint)" instead and will not satisfy the ruleset. +# +# Also copy .prettierrc, .prettierignore, .markdownlint.jsonc and +# .yamllint.yaml from nyuchi/.github into your repo root. + +name: Lint + +on: + pull_request: + push: + branches: [main] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +permissions: + contents: read + +jobs: + lint: + uses: nyuchi/.github/.github/workflows/reusable-lint.yml@main diff --git a/.markdownlint.jsonc b/.markdownlint.jsonc new file mode 100644 index 0000000..1a3974c --- /dev/null +++ b/.markdownlint.jsonc @@ -0,0 +1,39 @@ +// markdownlint-cli2 config for nyuchi/.github. +// +// Relaxed defaults that accommodate: +// - Long prose lines in docs (we format for readability, not width) +// - Inline HTML in the org profile (
) +// - Files that start with an HTML comment or a
instead of an H1 +// - Fenced code blocks without a language tag +// +// See https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md +{ + "default": true, + + // Line length — we wrap for readability, not at a fixed column. + "MD013": false, + + // Inline HTML — profile/README.md uses
for the + // landing-page layout and that's intentional. + "MD033": false, + + // First line must be a top-level heading — profile/README.md opens + // with an HTML comment, which is correct. + "MD041": false, + + // Fenced code blocks without a language — acceptable for output + // blocks and plain-text fences. + "MD040": false, + + // Duplicate headings are fine as long as they aren't siblings + // (e.g. "## Summary" appears in multiple docs; that's expected). + "MD024": { "siblings_only": true }, + + // Unordered list indentation — 2 spaces, matching our house style. + "MD007": { "indent": 2 }, + + // Table-column-style — re-enabled now that Prettier is in CI and + // auto-formats tables. Prettier's table output should satisfy + // MD060's "aligned" style. + "MD060": true, +} diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..b8d69cf --- /dev/null +++ b/.prettierignore @@ -0,0 +1,30 @@ +# Prettier ignore for nyuchi/.github. + +# Standard ignores +node_modules/ +.git/ + +# Files with structural meaning that Prettier would harm +LICENSE +CODEOWNERS +CODEOWNERS.example +.github/CODEOWNERS + +# YAML is handled by yamllint and actionlint, not Prettier — they have +# stronger guarantees about GitHub Actions semantics that Prettier does +# not understand (e.g. the `on:` truthy quirk). +*.yml +*.yaml + +# Governance documents are authored by the Founder as legal / formal +# documents. Prettier's markdown formatter reflows numbered paragraphs +# ("2.2 The company pursues...") after a list as loose list-item +# continuations, which corrupts the document's structure. Hand-format +# these files. +profile/governance/ + +# Lockfiles, generated output +*-lock.json +*-lock.yaml +package-lock.json +pnpm-lock.yaml diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..333987c --- /dev/null +++ b/.prettierrc @@ -0,0 +1,16 @@ +{ + "printWidth": 80, + "proseWrap": "preserve", + "tabWidth": 2, + "useTabs": false, + "endOfLine": "lf", + "trailingComma": "all", + "overrides": [ + { + "files": ["*.md", "*.mdx"], + "options": { + "embeddedLanguageFormatting": "off" + } + } + ] +} diff --git a/.yamllint.yaml b/.yamllint.yaml new file mode 100644 index 0000000..a280c3e --- /dev/null +++ b/.yamllint.yaml @@ -0,0 +1,57 @@ +# yamllint config for nyuchi/.github. +# +# Relaxed defaults that accommodate: +# - GitHub Actions workflows (which use `on:` — a YAML 1.1 boolean) +# - Long lines in shell heredocs and comment blocks inside workflows +# - Files without `---` document-start markers +# +# See https://yamllint.readthedocs.io/en/stable/configuration.html + +extends: default + +ignore: | + node_modules/ + +rules: + # 140-char limit. Workflow files have legitimately long shell URLs + # (the actionlint download script, action references) and issue- + # template `about:` strings render as a single line in the picker, + # so wrapping them would change user-visible behaviour. 140 is + # tight enough to flag truly excessive lines without forcing + # awkward breaks on URLs. Strict CI fails on any violation. + line-length: + max: 140 + level: error + allow-non-breakable-words: true + allow-non-breakable-inline-mappings: true + + # GitHub Actions uses `on:` as a key, which YAML 1.1 treats as a + # boolean. Disable the truthy check on keys to stop yamllint from + # rejecting every workflow. + truthy: + check-keys: false + level: error + + # We don't prefix YAML files with `---`. + document-start: disable + + # Be lenient about how many spaces follow `#` in comments. + comments: + min-spaces-from-content: 1 + + # Comments-indentation flags standalone comments that don't match the + # indent of surrounding content. Real-world configs use comments to + # delimit sections (long `# ----` separator banners) and to mark + # commented-out blocks at the level of the code they replace, neither + # of which fits the rule cleanly. Disabled. + comments-indentation: disable + + # GitHub issue forms have deeply nested lists and mappings. + indentation: + spaces: 2 + indent-sequences: consistent + + # Stops a warning on the trailing-empty-line check for files that + # end cleanly with a single newline. + empty-lines: + max-end: 1 diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 09dac2e..e4f3623 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -8,7 +8,6 @@ that does not ship its own. --> - # Contributor Covenant Code of Conduct ## Our Pledge @@ -21,19 +20,19 @@ We pledge to act and interact in ways that contribute to an open, welcoming, div Examples of behavior that contributes to a positive environment for our community include: -* Demonstrating empathy and kindness toward other people -* Being respectful of differing opinions, viewpoints, and experiences -* Giving and gracefully accepting constructive feedback -* Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience -* Focusing on what is best not just for us as individuals, but for the overall community +- Demonstrating empathy and kindness toward other people +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience +- Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: -* The use of sexualized language or imagery, and sexual attention or advances of any kind -* Trolling, insulting or derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or email address, without their explicit permission -* Other conduct which could reasonably be considered inappropriate in a professional setting +- The use of sexualized language or imagery, and sexual attention or advances of any kind +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or email address, without their explicit permission +- Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities @@ -47,7 +46,7 @@ This Code of Conduct applies within all community spaces, and also applies when ## Enforcement -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at **conduct@nyuchi.com**. All complaints will be reviewed and investigated promptly and fairly. +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at ****. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the reporter of any incident. @@ -92,4 +91,3 @@ For answers to common questions about this code of conduct, see the FAQ at [http [Mozilla CoC]: https://github.com/mozilla/diversity [FAQ]: https://www.contributor-covenant.org/faq [translations]: https://www.contributor-covenant.org/translations - diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 039f310..76c2076 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,7 +16,7 @@ written down in `mzizi-dev/mzizi`'s `MIGRATION.md` §1.1: So: **your commits land on `main` exactly as you wrote them, and stay there.** That changes how you should work. -- Write each commit as a coherent step, with a message that explains *why*. +- Write each commit as a coherent step, with a message that explains _why_. Nobody is going to squash your "wip" and "fix typo" commits away for you. - Clean the branch up before requesting review — `git rebase -i` on your own branch, not on `main`. diff --git a/ORG_STANDARDS.md b/ORG_STANDARDS.md index 96db1d7..2eb7492 100644 --- a/ORG_STANDARDS.md +++ b/ORG_STANDARDS.md @@ -17,17 +17,17 @@ Nine repos. Two members — `@bryanfawcett` (admin) and `@michellellawson` (member). **No teams exist**, which is why `.github/CODEOWNERS` names users rather than a `@mzizi-dev/...` handle. -| Repo | Public | Stack | State | -|---|---|---|---| -| [`mzizi`](https://github.com/mzizi-dev/mzizi) | yes | Rust | The language, compiler and `mz` CLI. Bundu Foundation IP. Has content and CI | -| [`mzizi-registry`](https://github.com/mzizi-dev/mzizi-registry) | yes | Next.js (+ Rust crates) on Vercel | The component registry and mzizi.dev. The largest repo, and the only one with its own community-health files | -| [`mzizi-console`](https://github.com/mzizi-dev/mzizi-console) | yes | Astro + Rust/Dioxus WASM islands | app.mzizi.dev. Has content and CI | -| [`mzizi-api-gateway`](https://github.com/mzizi-dev/mzizi-api-gateway) | yes | Pure-Rust Cloudflare Worker (workers-rs) | api.mzizi.dev. Has content and CI | -| [`mzizi-site`](https://github.com/mzizi-dev/mzizi-site) | yes | — | **Completely empty** — no commits at all. Not "a README": the API returns "This repository is empty" | -| [`mzizi-docs`](https://github.com/mzizi-dev/mzizi-docs) | yes | Mintlify (planned) | README and LICENSE only. No `.github/` directory, no CI | -| [`mzizi-roadmap`](https://github.com/mzizi-dev/mzizi-roadmap) | yes | — | README only. `mzizi`'s own history shows the roadmap being folded into `mzizi/design/ROADMAP.md`, so this repo may be vestigial | -| [`agent-tools`](https://github.com/mzizi-dev/agent-tools) | **no** | TypeScript / pnpm | MCP server, `fundi` agent, CLI, skills. The most CI of any repo — ten workflows | -| [`.github`](https://github.com/mzizi-dev/.github) | yes | — | This repo | +| Repo | Public | Stack | State | +| --------------------------------------------------------------------- | ------ | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | +| [`mzizi`](https://github.com/mzizi-dev/mzizi) | yes | Rust | The language, compiler and `mz` CLI. Bundu Foundation IP. Has content and CI | +| [`mzizi-registry`](https://github.com/mzizi-dev/mzizi-registry) | yes | Next.js (+ Rust crates) on Vercel | The component registry and mzizi.dev. The largest repo, and the only one with its own community-health files | +| [`mzizi-console`](https://github.com/mzizi-dev/mzizi-console) | yes | Astro + Rust/Dioxus WASM islands | app.mzizi.dev. Has content and CI | +| [`mzizi-api-gateway`](https://github.com/mzizi-dev/mzizi-api-gateway) | yes | Pure-Rust Cloudflare Worker (workers-rs) | api.mzizi.dev. Has content and CI | +| [`mzizi-site`](https://github.com/mzizi-dev/mzizi-site) | yes | — | **Completely empty** — no commits at all. Not "a README": the API returns "This repository is empty" | +| [`mzizi-docs`](https://github.com/mzizi-dev/mzizi-docs) | yes | Mintlify (planned) | README and LICENSE only. No `.github/` directory, no CI | +| [`mzizi-roadmap`](https://github.com/mzizi-dev/mzizi-roadmap) | yes | — | README only. `mzizi`'s own history shows the roadmap being folded into `mzizi/design/ROADMAP.md`, so this repo may be vestigial | +| [`agent-tools`](https://github.com/mzizi-dev/agent-tools) | **no** | TypeScript / pnpm | MCP server, `fundi` agent, CLI, skills. The most CI of any repo — ten workflows | +| [`.github`](https://github.com/mzizi-dev/.github) | yes | — | This repo | --- @@ -51,7 +51,7 @@ near the tip of `main`. Three consequences that are easy to get wrong: **1. Your commits are permanent, exactly as written.** Nothing folds them -together. Clean the branch up with an interactive rebase *on your own branch* +together. Clean the branch up with an interactive rebase _on your own branch_ before requesting review, and write messages that explain why. **2. The PR title becomes the merge commit body, not its subject.** Every @@ -93,11 +93,11 @@ Read from the workflow files in each repo's default branch. `ci.yml` triggers on push to `main` and pull requests to `main` **or** `claude/**`, with `concurrency` cancelling superseded runs off `main`. -| Job (check name) | What it runs | -|---|---| -| `compiler` | `cargo fmt -- --check`, `cargo clippy --all-targets -- -D warnings`, `cargo test`, all in `compiler/` | -| `compiler` (cont.) | `mz check ../examples/connectivity_bar.mz`, then `mz check` over **every** file in `primitives/`, using the built binary rather than the test harness | -| `secret scan` | `gitleaks detect` at `fetch-depth: 0` — full history, because this repo arrived via `git subtree split` and every commit reached CI for the first time at once | +| Job (check name) | What it runs | +| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `compiler` | `cargo fmt -- --check`, `cargo clippy --all-targets -- -D warnings`, `cargo test`, all in `compiler/` | +| `compiler` (cont.) | `mz check ../examples/connectivity_bar.mz`, then `mz check` over **every** file in `primitives/`, using the built binary rather than the test harness | +| `secret scan` | `gitleaks detect` at `fetch-depth: 0` — full history, because this repo arrived via `git subtree split` and every commit reached CI for the first time at once | `mzizi-lang-benchmark-dispatch.yml` is the second workflow. On push to `main` it dispatches to a held-out benchmark runner named by the @@ -108,24 +108,24 @@ held-out task set is deliberately kept out of the public repo — per rather than memorisation". Nothing here checks whether that runner exists. The `mz check` steps are the interesting part and are worth copying in -spirit: they assert the *shipped binary* still accepts the corpus, which is a +spirit: they assert the _shipped binary_ still accepts the corpus, which is a different claim from "the tests pass". ### `mzizi-console` — 1 workflow -| Job | What it runs | -|---|---| -| `rust` | fmt, clippy (host), `cargo test`, **and `cargo check --target wasm32-unknown-unknown --all-targets`** | -| `web` | pnpm 10.33.0, Node 22, `astro check`, `astro build`. The build is what proves the two toolchains compose — the island script references a bundle name derived from the crate name, so a rename that updates one and not the other fails here instead of serving a blank page | -| `secret scan` | gitleaks, full history | +| Job | What it runs | +| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `rust` | fmt, clippy (host), `cargo test`, **and `cargo check --target wasm32-unknown-unknown --all-targets`** | +| `web` | pnpm 10.33.0, Node 22, `astro check`, `astro build`. The build is what proves the two toolchains compose — the island script references a bundle name derived from the crate name, so a rename that updates one and not the other fails here instead of serving a blank page | +| `secret scan` | gitleaks, full history | ### `mzizi-api-gateway` — 1 workflow -| Job | What it runs | -|---|---| -| `rust` | fmt; **clippy against `wasm32-unknown-unknown`**, not the host, because the `worker` crate's API is `cfg`'d for that target; `cargo check --target wasm32-unknown-unknown`; `cargo test` | +| Job | What it runs | +| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `rust` | fmt; **clippy against `wasm32-unknown-unknown`**, not the host, because the `worker` crate's API is `cfg`'d for that target; `cargo check --target wasm32-unknown-unknown`; `cargo test` | | `worker build` | `cargo install worker-build --version ^0.8`, `worker-build --release`, then `wrangler@4 deploy --dry-run`. The workflow's own comment records why the version pin is load-bearing: worker-build must track the `worker` dependency's minor line, and a pre-0.7 toolchain hard-codes a wasm-bindgen CLI version that cannot match what the crate compiled against | -| `secret scan` | gitleaks, full history | +| `secret scan` | gitleaks, full history | ### `mzizi-registry` — 4 workflows @@ -133,20 +133,20 @@ different claim from "the tests pass". requires them under those exact strings: **Security Audit**, **Registry Snapshot**, **Rust**, **Lint**, **Type Check**, **Test**, **Build**. -`lint.yml` jobs are the opposite convention — names carry a `lint / ` prefix +`lint.yml` jobs are the opposite convention — names carry a `lint /` prefix (`lint / actionlint`, `lint / JSON validity`, `lint / prettier`, `lint / markdownlint`, `lint / yamllint`) because GitHub reports the bare `name:` field to the Checks API and the UI grouping label is not part of it. That asymmetry inside one repo is a live trap; the file itself documents it. Also present: `release.yml` (auto-release on a version bump) and -`reusable-ci-vite-plus.yml` — a reusable workflow that lives in the *registry* +`reusable-ci-vite-plus.yml` — a reusable workflow that lives in the _registry_ repo rather than here. Its header explains why, and the reason is now stale: see gap 7. Both `ci.yml` and `lint.yml` carry a `workflow_dispatch` trigger added after -an incident on 2026-08-26 where neither workflow produced any run for PR -#265 and there was no way to trigger them manually. +an incident on 2026-08-26 where neither workflow produced any run for +PR `#265` and there was no way to trigger them manually. Note the trigger difference: `mzizi-registry`'s workflows filter pull requests on `[main]` only, while the three Rust repos use `[main, "claude/**"]`. @@ -181,7 +181,7 @@ conditional compilation, a host-only dependency, `std` surface that does not exist on wasm32. A green native `cargo check` is not evidence about the artefact. -Both repos already handle this, and they handle it *differently*, correctly: +Both repos already handle this, and they handle it _differently_, correctly: - `mzizi-console` lints on the host and adds `cargo check --target wasm32-unknown-unknown --all-targets`. @@ -204,22 +204,22 @@ A reusable workflow is a `.yml` under `.github/workflows/` with As of 2026-09-11 this repo publishes three: -| Workflow | Purpose | Notes | -|---|---|---| -| `reusable-rust-ci.yml` | fmt / clippy / test / cross-target check | `target` and `clippy-on-target` inputs cover the WASM trap above. `working-directory` covers `mzizi`, whose crate lives in `compiler/` | -| `reusable-gitleaks.yml` | Secret scan | Runs the MIT binary directly, **not** `gitleaks/gitleaks-action`, which requires a paid licence for org repos. Defaults to gitleaks 8.21.2 — the version every repo already runs, so adoption changes no behaviour | -| `reusable-pr-title-lint.yml` | Conventional Commits on the PR title | `amannn/action-semantic-pull-request` pinned by commit SHA | +| Workflow | Purpose | Notes | +| ---------------------------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `reusable-rust-ci.yml` | fmt / clippy / test / cross-target check | `target` and `clippy-on-target` inputs cover the WASM trap above. `working-directory` covers `mzizi`, whose crate lives in `compiler/` | +| `reusable-gitleaks.yml` | Secret scan | Runs the MIT binary directly, **not** `gitleaks/gitleaks-action`, which requires a paid licence for org repos. Defaults to gitleaks 8.21.2 — the version every repo already runs, so adoption changes no behaviour | +| `reusable-pr-title-lint.yml` | Conventional Commits on the PR title | `amannn/action-semantic-pull-request` pinned by commit SHA | **Third-party actions are pinned by commit SHA, not tag.** A tag can be moved to point at different code; a SHA cannot. `actions/*` are first-party GitHub and stay on major tags. The pinned SHAs and what they resolved to on 2026-09-11: -| Action | SHA | Resolves to | -|---|---|---| -| `dtolnay/rust-toolchain` | `6bed076…` | head of the `stable` branch — this action publishes no semver tags, so a branch head is the only thing to pin | -| `Swatinem/rust-cache` | `6323deb…` | v2.9.2 (dereferenced from the annotated tag) | -| `amannn/action-semantic-pull-request` | `48f2562…` | v6.1.1, which is also where the floating `v6` tag pointed | +| Action | SHA | Resolves to | +| ------------------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------- | +| `dtolnay/rust-toolchain` | `6bed076…` | head of the `stable` branch — this action publishes no semver tags, so a branch head is the only thing to pin | +| `Swatinem/rust-cache` | `6323deb…` | v2.9.2 (dereferenced from the annotated tag) | +| `amannn/action-semantic-pull-request` | `48f2562…` | v6.1.1, which is also where the floating `v6` tag pointed | **No repo calls any of these yet.** They are published first so that adopting one is a small reviewable PR against a single repo, with a real CI run to @@ -268,11 +268,11 @@ repo-level: **`mzizi-registry` → ruleset "Default"** (id 14801708, active, no bypass actors): -| Rule | Parameters | -|---|---| -| `required_linear_history` | — | -| `pull_request` | 0 approvals required, review-thread resolution off, `allowed_merge_methods: ["merge", "squash", "rebase"]` | -| `required_status_checks` | `Lint`, `Type Check`, `Build`, `Security Audit`, `Test` | +| Rule | Parameters | +| ------------------------- | ---------------------------------------------------------------------------------------------------------- | +| `required_linear_history` | — | +| `pull_request` | 0 approvals required, review-thread resolution off, `allowed_merge_methods: ["merge", "squash", "rebase"]` | +| `required_status_checks` | `Lint`, `Type Check`, `Build`, `Security Audit`, `Test` | That ruleset is the org's only worked example of required status checks, and it is also broken — see gap 4. @@ -304,20 +304,20 @@ each file's `_comment`. Two things to settle before applying: Uniform across all nine unless noted. -| Setting | Value | Note | -|---|---|---| -| `allow_merge_commit` | true | The only permitted method | -| `allow_squash_merge` / `allow_rebase_merge` | false | MIGRATION.md §1.1 | -| `merge_commit_title` | `MERGE_MESSAGE` | "Merge pull request #N from …" | -| `merge_commit_message` | `PR_TITLE` | The PR title becomes the body | -| `delete_branch_on_merge` | **true** on all nine | Already correct — no cleanup needed | -| `allow_auto_merge` | true on `mzizi-registry`, `mzizi-api-gateway`, `agent-tools`; **false** on the other six | Inconsistent | -| `has_wiki` | false on `mzizi`, `mzizi-registry`, `mzizi-api-gateway`, `mzizi-site`; **true** on the other five | Unused surface, on by default | -| Licence | Apache-2.0 on seven; **none** on `mzizi-roadmap` and `.github` | | -| Secret scanning | **enabled on 2 of 8 public repos** — `mzizi-registry`, `mzizi-api-gateway` | | -| Secret scanning push protection | Same two | | -| Dependabot security updates | **disabled on all nine** | | -| Private vulnerability reporting | **enabled on 2 of 8** — `mzizi`, `mzizi-registry`. Not available on `agent-tools` (private repo) | Determines where a security report can actually be filed | +| Setting | Value | Note | +| ------------------------------------------- | ------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | +| `allow_merge_commit` | true | The only permitted method | +| `allow_squash_merge` / `allow_rebase_merge` | false | MIGRATION.md §1.1 | +| `merge_commit_title` | `MERGE_MESSAGE` | "Merge pull request #N from …" | +| `merge_commit_message` | `PR_TITLE` | The PR title becomes the body | +| `delete_branch_on_merge` | **true** on all nine | Already correct — no cleanup needed | +| `allow_auto_merge` | true on `mzizi-registry`, `mzizi-api-gateway`, `agent-tools`; **false** on the other six | Inconsistent | +| `has_wiki` | false on `mzizi`, `mzizi-registry`, `mzizi-api-gateway`, `mzizi-site`; **true** on the other five | Unused surface, on by default | +| Licence | Apache-2.0 on seven; **none** on `mzizi-roadmap` and `.github` | | +| Secret scanning | **enabled on 2 of 8 public repos** — `mzizi-registry`, `mzizi-api-gateway` | | +| Secret scanning push protection | Same two | | +| Dependabot security updates | **disabled on all nine** | | +| Private vulnerability reporting | **enabled on 2 of 8** — `mzizi`, `mzizi-registry`. Not available on `agent-tools` (private repo) | Determines where a security report can actually be filed | --- @@ -343,7 +343,7 @@ security to a private advisory), `SECURITY.md`, `CONTRIBUTING.md`, repo can supply as defaults is CODE_OF_CONDUCT.md, CONTRIBUTING.md, discussion category forms, FUNDING.yml, issue and PR templates, SECURITY.md and SUPPORT.md. CODEOWNERS is not on it, and the CODEOWNERS docs read the - file from `.github/`, the root, or `docs/` *of the repository*. So + file from `.github/`, the root, or `docs/` _of the repository_. So `.github/CODEOWNERS` in this repo governs this repo and nothing else. `CODEOWNERS.example` at the root is the template to copy into each repo. This is gap 14. @@ -385,7 +385,7 @@ repo.** **4. `mzizi-registry`'s ruleset contradicts the merge-only convention.** Its "Default" ruleset requires `required_linear_history`, which blocks merge -commits — while the repo's only enabled merge method *is* the merge commit. +commits — while the repo's only enabled merge method _is_ the merge commit. The next PR merged there with the merge button should be rejected by the ruleset. Stated as a prediction rather than an observation, honestly: the last merges on that repo (PRs #317, #318, 2026-09-08) produced single-parent diff --git a/README.md b/README.md index 72fb627..d4c66c1 100644 --- a/README.md +++ b/README.md @@ -10,15 +10,15 @@ in each repo today, and an explicit list of what does not exist yet. ## What is in here -| Path | Applies to | -|---|---| -| [`.github/CODEOWNERS`](./.github/CODEOWNERS) | **This repo only.** CODEOWNERS is not inheritable — see [`CODEOWNERS.example`](./CODEOWNERS.example) | -| [`.github/PULL_REQUEST_TEMPLATE.md`](./.github/PULL_REQUEST_TEMPLATE.md) | Every repo without its own | -| [`.github/ISSUE_TEMPLATE/`](./.github/ISSUE_TEMPLATE) | Every repo without its own | -| [`SECURITY.md`](./SECURITY.md) · [`CONTRIBUTING.md`](./CONTRIBUTING.md) · [`CODE_OF_CONDUCT.md`](./CODE_OF_CONDUCT.md) · [`SUPPORT.md`](./SUPPORT.md) | Every repo without its own | -| [`.github/workflows/reusable-*.yml`](./.github/workflows) | Any repo that calls them — opt-in, per repo | -| [`github-rulesets/`](./github-rulesets) | Proposals. **Not applied.** | -| [`CODEOWNERS.example`](./CODEOWNERS.example) · [`dependabot.example.yml`](./dependabot.example.yml) | Templates to copy — neither CODEOWNERS nor Dependabot has an org-wide fallback | +| Path | Applies to | +| ----------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | +| [`.github/CODEOWNERS`](./.github/CODEOWNERS) | **This repo only.** CODEOWNERS is not inheritable — see [`CODEOWNERS.example`](./CODEOWNERS.example) | +| [`.github/PULL_REQUEST_TEMPLATE.md`](./.github/PULL_REQUEST_TEMPLATE.md) | Every repo without its own | +| [`.github/ISSUE_TEMPLATE/`](./.github/ISSUE_TEMPLATE) | Every repo without its own | +| [`SECURITY.md`](./SECURITY.md) · [`CONTRIBUTING.md`](./CONTRIBUTING.md) · [`CODE_OF_CONDUCT.md`](./CODE_OF_CONDUCT.md) · [`SUPPORT.md`](./SUPPORT.md) | Every repo without its own | +| [`.github/workflows/reusable-*.yml`](./.github/workflows) | Any repo that calls them — opt-in, per repo | +| [`github-rulesets/`](./github-rulesets) | Proposals. **Not applied.** | +| [`CODEOWNERS.example`](./CODEOWNERS.example) · [`dependabot.example.yml`](./dependabot.example.yml) | Templates to copy — neither CODEOWNERS nor Dependabot has an org-wide fallback | ## Reusable workflows @@ -32,11 +32,11 @@ jobs: uses: mzizi-dev/.github/.github/workflows/reusable-gitleaks.yml@main ``` -| Workflow | What it does | -|---|---| -| [`reusable-rust-ci.yml`](./.github/workflows/reusable-rust-ci.yml) | fmt, clippy, test, and an optional check against a second target — `wasm32-unknown-unknown` is the one that matters for `mzizi-console` and `mzizi-api-gateway` | -| [`reusable-gitleaks.yml`](./.github/workflows/reusable-gitleaks.yml) | Secret scan, running the MIT-licensed binary directly rather than the paid-licence wrapper action | -| [`reusable-pr-title-lint.yml`](./.github/workflows/reusable-pr-title-lint.yml) | Conventional Commits on the PR title | +| Workflow | What it does | +| ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [`reusable-rust-ci.yml`](./.github/workflows/reusable-rust-ci.yml) | fmt, clippy, test, and an optional check against a second target — `wasm32-unknown-unknown` is the one that matters for `mzizi-console` and `mzizi-api-gateway` | +| [`reusable-gitleaks.yml`](./.github/workflows/reusable-gitleaks.yml) | Secret scan, running the MIT-licensed binary directly rather than the paid-licence wrapper action | +| [`reusable-pr-title-lint.yml`](./.github/workflows/reusable-pr-title-lint.yml) | Conventional Commits on the PR title | No repo calls these yet — they are published here first so adoption is a reviewable PR per repo rather than a big-bang change. See ORG_STANDARDS.md. @@ -44,8 +44,8 @@ reviewable PR per repo rather than a big-bang change. See ORG_STANDARDS.md. ## This org is merge-only Squash and rebase merging are disabled on all nine repos, deliberately: -`mzizi/MIGRATION.md` §1.1 — *"Squash discards the per-commit reasoning this -project depends on."* +`mzizi/MIGRATION.md` §1.1 — _"Squash discards the per-commit reasoning this +project depends on."_ Merge with `gh pr merge --merge --delete-branch`. Write your commits for the person reading them in a year; they are not going to be squashed away. diff --git a/SECURITY.md b/SECURITY.md index 9b7da98..261f689 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -12,14 +12,14 @@ points at a stale URL (see "Known problems" below). Report privately through GitHub Security Advisories, on the repo the finding affects: -| Repo | Private reporting | Advisory link | -|---|---|---| -| `mzizi` | **enabled** | | -| `mzizi-registry` | **enabled** | | -| `mzizi-console` | not enabled | — | -| `mzizi-api-gateway` | not enabled | — | -| `mzizi-site`, `mzizi-docs`, `mzizi-roadmap`, `.github` | not enabled | — | -| `agent-tools` | n/a — private repo | — | +| Repo | Private reporting | Advisory link | +| ------------------------------------------------------ | ------------------ | --------------------------------------------------------------------- | +| `mzizi` | **enabled** | | +| `mzizi-registry` | **enabled** | | +| `mzizi-console` | not enabled | — | +| `mzizi-api-gateway` | not enabled | — | +| `mzizi-site`, `mzizi-docs`, `mzizi-roadmap`, `.github` | not enabled | — | +| `agent-tools` | n/a — private repo | — | Verified 2026-09-11 against the GitHub API. If the repo you need is in the "not enabled" rows, **report against `mzizi-dev/mzizi`** and say in the @@ -27,7 +27,7 @@ report which component it actually concerns; it reaches the same maintainers. Enabling private reporting on the remaining repos is a tracked gap — see [ORG_STANDARDS.md](./ORG_STANDARDS.md#known-gaps). -If GitHub advisories are unavailable to you, email **security@nyuchi.com** +If GitHub advisories are unavailable to you, email **** with the same information. Nyuchi Africa operates the Mzizi surfaces commercially and that mailbox is the one already in use for this ecosystem; it is not a separate team. @@ -51,14 +51,14 @@ sent early is more useful than a complete one sent late. In scope: -| Repo | Surface | -|---|---| -| `mzizi` | The compiler and the `mz` CLI — anything where checking or compiling untrusted `.mz` source can execute code, escape the working directory, or exhaust the host | -| `mzizi-api-gateway` | api.mzizi.dev — the Worker: routing, auth token handling, request and response validation | -| `mzizi-registry` | mzizi.dev — the registry API and the component source it serves | -| `mzizi-console` | app.mzizi.dev — the console and its WASM islands | -| `mzizi-site`, `mzizi-docs` | The public site and documentation | -| This repo | The reusable workflows, and the ruleset definitions under `github-rulesets/` | +| Repo | Surface | +| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `mzizi` | The compiler and the `mz` CLI — anything where checking or compiling untrusted `.mz` source can execute code, escape the working directory, or exhaust the host | +| `mzizi-api-gateway` | api.mzizi.dev — the Worker: routing, auth token handling, request and response validation | +| `mzizi-registry` | mzizi.dev — the registry API and the component source it serves | +| `mzizi-console` | app.mzizi.dev — the console and its WASM islands | +| `mzizi-site`, `mzizi-docs` | The public site and documentation | +| This repo | The reusable workflows, and the ruleset definitions under `github-rulesets/` | Out of scope: volumetric denial of service, findings against Cloudflare or Vercel themselves, missing headers with no demonstrated impact, and raw diff --git a/SUPPORT.md b/SUPPORT.md index 3905ae2..057d181 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -2,26 +2,26 @@ ## Documentation -| Surface | Where | Status | -|---|---|---| -| Framework docs | | `mzizi-docs` holds only a README and LICENSE today — the site is being built | -| Component registry | | `mzizi-registry` is the live registry and portal | -| Console | | `mzizi-console` | -| API | | `mzizi-api-gateway` | -| Language, charter, RFCs | [`mzizi-dev/mzizi`](https://github.com/mzizi-dev/mzizi) | `CHARTER.md` is the authoritative statement of what this project is for | +| Surface | Where | Status | +| ----------------------- | ------------------------------------------------------- | ---------------------------------------------------------------------------- | +| Framework docs | | `mzizi-docs` holds only a README and LICENSE today — the site is being built | +| Component registry | | `mzizi-registry` is the live registry and portal | +| Console | | `mzizi-console` | +| API | | `mzizi-api-gateway` | +| Language, charter, RFCs | [`mzizi-dev/mzizi`](https://github.com/mzizi-dev/mzizi) | `CHARTER.md` is the authoritative statement of what this project is for | ## Where to raise what -| What | Where | -|---|---| -| A compiler bug, a language question, an `mz` CLI problem | An issue on [`mzizi`](https://github.com/mzizi-dev/mzizi/issues) | -| A component, token or registry-API problem | An issue on [`mzizi-registry`](https://github.com/mzizi-dev/mzizi-registry/issues) | -| Something wrong at app.mzizi.dev | An issue on [`mzizi-console`](https://github.com/mzizi-dev/mzizi-console/issues) | -| Something wrong at api.mzizi.dev | An issue on [`mzizi-api-gateway`](https://github.com/mzizi-dev/mzizi-api-gateway/issues) | -| A documentation error | An issue on [`mzizi-docs`](https://github.com/mzizi-dev/mzizi-docs/issues) | -| Roadmap and sequencing | [`mzizi-roadmap`](https://github.com/mzizi-dev/mzizi-roadmap/issues) | -| CI, governance, org standards, this file | An issue on [`mzizi-dev/.github`](https://github.com/mzizi-dev/.github/issues) | -| A security vulnerability | **Not an issue.** See [SECURITY.md](./SECURITY.md) | +| What | Where | +| -------------------------------------------------------- | ---------------------------------------------------------------------------------------- | +| A compiler bug, a language question, an `mz` CLI problem | An issue on [`mzizi`](https://github.com/mzizi-dev/mzizi/issues) | +| A component, token or registry-API problem | An issue on [`mzizi-registry`](https://github.com/mzizi-dev/mzizi-registry/issues) | +| Something wrong at app.mzizi.dev | An issue on [`mzizi-console`](https://github.com/mzizi-dev/mzizi-console/issues) | +| Something wrong at api.mzizi.dev | An issue on [`mzizi-api-gateway`](https://github.com/mzizi-dev/mzizi-api-gateway/issues) | +| A documentation error | An issue on [`mzizi-docs`](https://github.com/mzizi-dev/mzizi-docs/issues) | +| Roadmap and sequencing | [`mzizi-roadmap`](https://github.com/mzizi-dev/mzizi-roadmap/issues) | +| CI, governance, org standards, this file | An issue on [`mzizi-dev/.github`](https://github.com/mzizi-dev/.github/issues) | +| A security vulnerability | **Not an issue.** See [SECURITY.md](./SECURITY.md) | `agent-tools` is private. If your question is about the MCP server, `fundi`, the CLI or the skills and you cannot open an issue there, raise it on