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