You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A proposal for review, not a roadmap. Continues the work of issue #2 on the automation side. Drafted 2026-04-21.
What this is
Issue #2 added the community files — CODE_OF_CONDUCT.md, CONTRIBUTING.md, SECURITY.md, SUPPORT.md, CHANGELOG.md, issue templates, PR template. That made the repo legible to anyone who lands on it cold.
This proposal extends that work to the automation and hardening side: the checks and settings that make the repo defend itself against stale dependencies, known CVEs, leaked secrets, unreviewed supply-chain changes, and link rot as code starts to land. None of this is urgent today because there's no compiled code yet — and that's exactly why it's the right time. Most of these controls are cheaper to install before the first skill ships than after.
Goal: by the time issue #1 Phase 1 lands its first real skill, the repo already has the guardrails in place to review it safely.
No .github/workflows/ directory. No dependabot.yml. No CodeQL. No secret scanning enforcement. No Scorecard. No branch protection documented. No dependency pinning policy. No link checking. No .editorconfig.
Recommended additions
Each item below: one line of what, one line of why. Implementation details belong in the work when it happens, not here.
Repo settings (no files needed)
These are all one-click toggles in GitHub repo settings. They're free on public repos and they're the highest leverage per unit of effort.
Secret scanning + push protection. Blocks pushes that contain patterns from GitHub's partner pattern catalog (AWS keys, GitHub PATs, Stripe keys, and hundreds of other documented partner patterns — the exact count drifts as partners are added). Free for public repos. This is the single largest preventive control available. How to verify: push a deliberately fake AWS key on a throwaway branch; push should be rejected with a secret-scanning block message.
Private vulnerability reporting. Gives researchers a private channel that integrates with GH Security Advisories. Backs the public commitment in SECURITY.md with actual workflow. Free, one toggle. How to verify: the "Report a vulnerability" button appears on the repo's Security tab.
Dependency graph + Dependabot alerts. Free for public. Dependency graph is already on by default; alerts need to be confirmed on. Alerts are the read-path; the dependabot.yml file below is the write-path. How to verify: Security → Dependabot shows alerts (zero is fine — the presence of the pane is the signal).
Branch protection on main. Enable the ruleset with: require signed commits, require linear history, disable force-push, require at least one review, require status checks to pass, and apply rules to administrators. The single-maintainer exception is to use a bypass on a case-by-case basis (tracked in the ruleset audit log), not to carve administrators out of the rules wholesale. The moment a second reviewer exists, the bypass path closes. Signed commits give tamper-evidence; "apply to administrators" is what keeps that evidence meaningful. How to verify:gh api repos/ArangoGutierrez/Maya/rulesets returns the configured ruleset with enforcement: active and the bypass list empty by default.
.github/dependabot.yml
Start with the github-actions ecosystem only, since that's what's about to exist. Weekly cadence, grouped updates to keep PR noise low. Add pip, gomod, npm ecosystems as they appear. Don't enable an ecosystem speculatively — Dependabot opens PRs against empty manifests and looks broken. How to verify: within one week of landing the first workflow that uses third-party Actions, Dependabot opens a PR proposing a version bump for at least one of them; absence of that PR within two weeks means the config isn't being picked up.
.github/workflows/codeql.yml
GitHub's CodeQL code scanning. CodeQL requires at least one language — there's no "no-op" configuration. Two ways to install this cleanly now:
Scope to the actions language. CodeQL supports scanning workflow files themselves for security issues (injection via untrusted inputs, overly broad permissions, unsafe pull_request_target patterns). Since this proposal adds several workflows, the actions analyzer has real signal from day one.
Or defer until Phase 1 lands code. When the first Python or Go file lands, add the matching language to the same workflow. Bash is not covered by CodeQL today; shellcheck (below) is the answer for bash.
Recommendation: install with actions scope now, add Python/Go as they arrive. How to verify: after the workflow lands, the repo's Security → Code scanning alerts page shows "No alerts" rather than "No analysis run," confirming CodeQL actually executed.
.github/workflows/shellcheck.yml
maya, setup.sh, and every skill in skills/ are bash. ludeeus/action-shellcheck@<sha> catches real bugs (quoting, unset variables, pipe-in-loop surprises) in seconds. This is the highest-signal lint the repo can run today given the current language mix. How to verify: open a throwaway PR that adds rm -rf $FOO (unquoted variable) to a shell script; the workflow should fail with SC2086.
.github/workflows/lint-prose.yml
The repo is >80% prose. One broken front-matter block in config/openclaw.yaml or a dead link in SOUL.md shouldn't make it through PR review silently. Bundle three linters in one workflow:
yamllint on config/**/*.yml, config/**/*.yaml, workflow files, dependabot config.
markdownlint-cli2 on **/*.md, scoped config that's permissive enough not to fight existing style.
lychee (link checker) on a separate schedule — nightly, not per-PR — since external links change state independently of commits. A broken link becomes an issue, not a merge block.
.github/workflows/gitleaks.yml
Belt-and-suspenders on top of GitHub secret scanning. Gitleaks matters even when GH scanning is on, but only if the Maya-specific patterns are stored correctly — see the pattern-storage note below; getting this wrong would commit the PII this workflow is meant to prevent.
Custom patterns for Maya's privacy stance.AGENTS.md notes that some regulars' names are known. If any of those names land in a log fixture, test data, or a copy-pasted transcript, a custom rule catches what GH's generic scanner won't. This is a precursor to Phase 3 of issue Proposal: improvement plan from initial repo audit #1 (privacy-in-code) — not a replacement for the Phase 3 sanitizer, which does text-output redaction at runtime.
Custom patterns as a complement, not a substitute. GitHub secret scanning scans full repo history on enablement, so the "gitleaks finds history leaks GH misses" framing is wrong — the real value is custom patterns, not history coverage.
Pattern storage (critical). The Maya-specific pattern list must not be committed to the repo. A file named .gitleaks.toml with a regex list that includes regulars' names is exactly the leak the workflow is trying to prevent. Three acceptable storage models:
Org- or repo-secret. Store the pattern file content as a GitHub Actions secret; the workflow writes it to a temp file at run-time and deletes it after. The pattern list never lands on disk in the repo.
Private sidecar repo. A maya-privacy-patterns private repo, pulled via a deploy-key at workflow start. Audit trail lives in that repo, not this one.
Hashed tokens. Commit a .gitleaks.toml in the repo that matches hashes of sensitive tokens, not the tokens themselves. Requires a small preprocessing step in the sanitizer to compute the same hashes. Viable, more moving parts.
Pick one before the workflow lands. Storing the raw pattern list in the repo, even gitignored, is not an option — .gitignore doesn't help once a careless commit lands. How to verify: add a file to a throwaway branch containing a seeded test token known to match the pattern list; gitleaks should fail the PR. Remove the file before merge.
.github/workflows/scorecard.yml
OpenSSF Scorecard runs a weekly audit across the current check set — branch protection, signed commits, pinned dependencies, token permissions, CI tests, code review, SAST, and others. Publishes a public score to securityscorecards.dev. Adding the badge to README gives contributors and users a one-glance trust signal. How to verify: after two weekly runs, the score is stable; baseline that number and alert (via a repo issue) if a future run drops it by ≥ 1.0.
OpenSSF Best Practices badge (passing / bronze tier)
Separate from Scorecard. A one-time self-assessment at bestpractices.coreinfrastructure.org. The "passing" (bronze) tier has a fixed criterion list covering basics like CoC, contribution guide, license, vulnerability reporting, version control hygiene, and a handful of automated-test and release criteria. Several are already met by issue #2 work; others (automated tests, release process) aren't applicable until Phase 1 lands code. A good chunk of the form can be filled today; the rest is revisited after Phase 1 and Phase 5. Silver and Gold tiers require more process than Maya should carry today. How to verify: the badge URL from the application is embedded in the README and resolves to a "passing" or "in_progress" page.
Pin all Actions by commit SHA, scope workflow permissions, harden runners
Three layered controls, all cheap, none sufficient alone:
1. SHA pin every Action reference. 40-char SHA, not a tag, with the tag as an inline comment:
Tag references are mutable; SHAs aren't. Pinned consumers of tj-actions/changed-files were unaffected by the March 2025 compromise — the incident itself wasn't mitigated by pinning, but the blast radius for pinned callers was zero. Dependabot bumps SHA-pinned Actions via its github-actions ecosystem, so this is not ongoing toil.
2. Default GITHUB_TOKEN to minimal permissions. Top-level permissions: {} in every workflow, with jobs opting into the specific scopes they need. Default-permissive tokens are the higher-impact half of the supply-chain story — if an Action is compromised but the token has no write scope, it can't tag releases, push code, or open PRs.
3. Use step-security/harden-runner on every workflow. Egress-policy-enforced runners block outbound network traffic to anything not on an allowlist. This is the control that would have tripped the tj-actions exfiltration at run-time, independent of whether the SHA was pinned. Start in audit mode for two weeks, then flip to enforcement once the allowlist is stable.
How to verify each: (1) grep -L '@[a-f0-9]\{40\}' .github/workflows/*.yml returns empty; (2) every workflow file has a top-level permissions: key; (3) step-security/harden-runner appears as the first step of every job.
.editorconfig
Two-space YAML, LF line endings, UTF-8, trim trailing whitespace, final newline. Kills a class of PR noise ("fix whitespace" commits) before it happens. Ten lines, every editor respects it.
CITATION.cff
DREAMS.md and the README frame this as a public, buildable-by-others project. A CITATION.cff makes citation unambiguous if a bar owner, a researcher, or a blog writer references the project. Ten-line YAML; GitHub auto-generates BibTeX from it on the repo page.
SBOM on releases (deferred)
Once CHANGELOG gets a tagged release, each release should carry an SBOM. Two options: (a) GitHub's built-in dependency-graph SBOM export (gh api repos/:owner/:repo/dependency-graph/sbom) stitched into the release workflow, or (b) anchore/sbom-action which writes SPDX or CycloneDX directly. No code yet → no releases yet → ship this when the first tag does.
What to skip (for now)
Keeping this list explicit so future conversations don't re-litigate.
Legal overhead for a single-maintainer MIT project. Revisit if external contributions grow.
FUNDING.yml
Only when sponsorships are actually being accepted.
Release-please / semantic-release
No code, no tags, no releases. Install when first release happens, not before.
Sigstore / cosign
Relevant when signed container images or signed binaries exist. Issue #1 Phase 0-1 hasn't produced any yet.
Renovate bot
Dependabot is sufficient at this scale. Renovate's advantages (custom managers, grouping rules) only pay off when dependency count crosses into the hundreds.
ZAP / OWASP dynamic scans
No runtime service exposed on the public internet. Relevant when / if a web surface ships.
Fuzzing (oss-fuzz, cifuzz)
Fuzzing is overkill until there's a real input-parsing surface in the codebase.
Trivy / container scans
No container images yet. Ship the workflow with the first image build, not before.
Stale bot
At ~2 issues total, there's nothing to stale.
Triage automation (issue labels)
Label by hand until there are enough issues to justify the YAML.
Suggested order
Ordered by leverage-per-minute. All of this is non-urgent — ship incrementally, in single-concern PRs that each address one row.
Repo settings — secret scanning + push protection + private vuln reporting + branch protection on main with signed commits + linear history. No files, ~10 minutes, highest leverage.
OpenSSF Best Practices Bronze application.~30 minutes, mostly filling a form.
CITATION.cff.~5 minutes.
Pin every action by SHA as the prior workflows land. Can be done alongside each workflow PR rather than as a separate pass. Included in items 4–8.
Total: roughly 2.5 hours of focused work, spread across eight to ten small PRs, each independently reviewable.
What ships in the first PR: items 1, 2, 3 (repo settings + dependabot.yml + .editorconfig). It's the smallest coherent unit — three changes, one concern ("turn on the defaults"). Everything after can be its own PR.
Phase 0 (repo consistency) is not affected — this work touches .github/ and repo settings, not the content files Phase 0 is reconciling.
Phase 1 (skill contract + first skill) gets cleaner — by the time the first real skill lands, shellcheck catches bash bugs in PR review, secret scanning catches credentials, and branch protection makes the history legible.
Phase 3 (privacy in code) has a precursor here — the gitleaks workflow with custom patterns catches one class of leak (committed PII) at CI time, and nothing more. It does not fulfill Phase 3. Phase 3's sanitizer, hard-stops function, and voice check operate at runtime on outgoing text/audio; gitleaks only sees what gets committed. Both are needed; this proposal only ships the first half.
Phase 4 (security hardening) is separate work — that's the Mac Mini / Spark side. This is the repo side. They don't overlap; they complement.
Open as a single meta-issue with the checklist structure above. Each recommended-addition section becomes a checkbox. When a contributor picks up an item, they open a small follow-up PR that references the meta-issue (Refs: #<this-issue>); the meta-issue's checklist gets checked when the PR merges.
Suggested labels: meta, ci, security, good-first-issue on the individual sub-items that are genuinely small (e.g., .editorconfig, CITATION.cff).
No milestone until Phase 1 of issue Proposal: improvement plan from initial repo audit #1 is assigned one; at that point, slot the "first PR bundle" (repo settings + dependabot + .editorconfig) into the same milestone so the guardrails land with (or before) the first real code.
Proposal: GitHub open-source best-practices rampup (automation & hardening)
A proposal for review, not a roadmap. Continues the work of issue #2 on the automation side. Drafted 2026-04-21.
What this is
Issue #2 added the community files —
CODE_OF_CONDUCT.md,CONTRIBUTING.md,SECURITY.md,SUPPORT.md,CHANGELOG.md, issue templates, PR template. That made the repo legible to anyone who lands on it cold.This proposal extends that work to the automation and hardening side: the checks and settings that make the repo defend itself against stale dependencies, known CVEs, leaked secrets, unreviewed supply-chain changes, and link rot as code starts to land. None of this is urgent today because there's no compiled code yet — and that's exactly why it's the right time. Most of these controls are cheaper to install before the first skill ships than after.
Goal: by the time issue #1 Phase 1 lands its first real skill, the repo already has the guardrails in place to review it safely.
What's already solid
CODE_OF_CONDUCT,CONTRIBUTING,SECURITY,SUPPORT,CHANGELOG) ✅.github/✅What's missing
No
.github/workflows/directory. Nodependabot.yml. No CodeQL. No secret scanning enforcement. No Scorecard. No branch protection documented. No dependency pinning policy. No link checking. No.editorconfig.Recommended additions
Each item below: one line of what, one line of why. Implementation details belong in the work when it happens, not here.
Repo settings (no files needed)
These are all one-click toggles in GitHub repo settings. They're free on public repos and they're the highest leverage per unit of effort.
SECURITY.mdwith actual workflow. Free, one toggle. How to verify: the "Report a vulnerability" button appears on the repo's Security tab.dependabot.ymlfile below is the write-path. How to verify: Security → Dependabot shows alerts (zero is fine — the presence of the pane is the signal).main. Enable the ruleset with: require signed commits, require linear history, disable force-push, require at least one review, require status checks to pass, and apply rules to administrators. The single-maintainer exception is to use a bypass on a case-by-case basis (tracked in the ruleset audit log), not to carve administrators out of the rules wholesale. The moment a second reviewer exists, the bypass path closes. Signed commits give tamper-evidence; "apply to administrators" is what keeps that evidence meaningful. How to verify:gh api repos/ArangoGutierrez/Maya/rulesetsreturns the configured ruleset withenforcement: activeand the bypass list empty by default..github/dependabot.ymlStart with the
github-actionsecosystem only, since that's what's about to exist. Weekly cadence, grouped updates to keep PR noise low. Addpip,gomod,npmecosystems as they appear. Don't enable an ecosystem speculatively — Dependabot opens PRs against empty manifests and looks broken. How to verify: within one week of landing the first workflow that uses third-party Actions, Dependabot opens a PR proposing a version bump for at least one of them; absence of that PR within two weeks means the config isn't being picked up..github/workflows/codeql.ymlGitHub's CodeQL code scanning. CodeQL requires at least one language — there's no "no-op" configuration. Two ways to install this cleanly now:
actionslanguage. CodeQL supports scanning workflow files themselves for security issues (injection via untrusted inputs, overly broadpermissions, unsafepull_request_targetpatterns). Since this proposal adds several workflows, theactionsanalyzer has real signal from day one.shellcheck(below) is the answer for bash.Recommendation: install with
actionsscope now, add Python/Go as they arrive. How to verify: after the workflow lands, the repo's Security → Code scanning alerts page shows "No alerts" rather than "No analysis run," confirming CodeQL actually executed..github/workflows/shellcheck.ymlmaya,setup.sh, and every skill inskills/are bash.ludeeus/action-shellcheck@<sha>catches real bugs (quoting, unset variables, pipe-in-loop surprises) in seconds. This is the highest-signal lint the repo can run today given the current language mix. How to verify: open a throwaway PR that addsrm -rf $FOO(unquoted variable) to a shell script; the workflow should fail with SC2086..github/workflows/lint-prose.ymlThe repo is >80% prose. One broken front-matter block in
config/openclaw.yamlor a dead link inSOUL.mdshouldn't make it through PR review silently. Bundle three linters in one workflow:yamllintonconfig/**/*.yml,config/**/*.yaml, workflow files, dependabot config.markdownlint-cli2on**/*.md, scoped config that's permissive enough not to fight existing style.lychee(link checker) on a separate schedule — nightly, not per-PR — since external links change state independently of commits. A broken link becomes an issue, not a merge block..github/workflows/gitleaks.ymlBelt-and-suspenders on top of GitHub secret scanning. Gitleaks matters even when GH scanning is on, but only if the Maya-specific patterns are stored correctly — see the pattern-storage note below; getting this wrong would commit the PII this workflow is meant to prevent.
AGENTS.mdnotes that some regulars' names are known. If any of those names land in a log fixture, test data, or a copy-pasted transcript, a custom rule catches what GH's generic scanner won't. This is a precursor to Phase 3 of issue Proposal: improvement plan from initial repo audit #1 (privacy-in-code) — not a replacement for the Phase 3 sanitizer, which does text-output redaction at runtime.Pattern storage (critical). The Maya-specific pattern list must not be committed to the repo. A file named
.gitleaks.tomlwith a regex list that includes regulars' names is exactly the leak the workflow is trying to prevent. Three acceptable storage models:maya-privacy-patternsprivate repo, pulled via a deploy-key at workflow start. Audit trail lives in that repo, not this one..gitleaks.tomlin the repo that matches hashes of sensitive tokens, not the tokens themselves. Requires a small preprocessing step in the sanitizer to compute the same hashes. Viable, more moving parts.Pick one before the workflow lands. Storing the raw pattern list in the repo, even gitignored, is not an option —
.gitignoredoesn't help once a careless commit lands. How to verify: add a file to a throwaway branch containing a seeded test token known to match the pattern list; gitleaks should fail the PR. Remove the file before merge..github/workflows/scorecard.ymlOpenSSF Scorecard runs a weekly audit across the current check set — branch protection, signed commits, pinned dependencies, token permissions, CI tests, code review, SAST, and others. Publishes a public score to securityscorecards.dev. Adding the badge to README gives contributors and users a one-glance trust signal. How to verify: after two weekly runs, the score is stable; baseline that number and alert (via a repo issue) if a future run drops it by ≥ 1.0.
OpenSSF Best Practices badge (passing / bronze tier)
Separate from Scorecard. A one-time self-assessment at bestpractices.coreinfrastructure.org. The "passing" (bronze) tier has a fixed criterion list covering basics like CoC, contribution guide, license, vulnerability reporting, version control hygiene, and a handful of automated-test and release criteria. Several are already met by issue #2 work; others (automated tests, release process) aren't applicable until Phase 1 lands code. A good chunk of the form can be filled today; the rest is revisited after Phase 1 and Phase 5. Silver and Gold tiers require more process than Maya should carry today. How to verify: the badge URL from the application is embedded in the README and resolves to a "passing" or "in_progress" page.
Pin all Actions by commit SHA, scope workflow permissions, harden runners
Three layered controls, all cheap, none sufficient alone:
1. SHA pin every Action reference. 40-char SHA, not a tag, with the tag as an inline comment:
Tag references are mutable; SHAs aren't. Pinned consumers of
tj-actions/changed-fileswere unaffected by the March 2025 compromise — the incident itself wasn't mitigated by pinning, but the blast radius for pinned callers was zero. Dependabot bumps SHA-pinned Actions via itsgithub-actionsecosystem, so this is not ongoing toil.2. Default
GITHUB_TOKENto minimal permissions. Top-levelpermissions: {}in every workflow, with jobs opting into the specific scopes they need. Default-permissive tokens are the higher-impact half of the supply-chain story — if an Action is compromised but the token has no write scope, it can't tag releases, push code, or open PRs.3. Use
step-security/harden-runneron every workflow. Egress-policy-enforced runners block outbound network traffic to anything not on an allowlist. This is the control that would have tripped the tj-actions exfiltration at run-time, independent of whether the SHA was pinned. Start in audit mode for two weeks, then flip to enforcement once the allowlist is stable.How to verify each: (1)
grep -L '@[a-f0-9]\{40\}' .github/workflows/*.ymlreturns empty; (2) every workflow file has a top-levelpermissions:key; (3)step-security/harden-runnerappears as the first step of every job..editorconfigTwo-space YAML, LF line endings, UTF-8, trim trailing whitespace, final newline. Kills a class of PR noise ("fix whitespace" commits) before it happens. Ten lines, every editor respects it.
CITATION.cffDREAMS.mdand the README frame this as a public, buildable-by-others project. ACITATION.cffmakes citation unambiguous if a bar owner, a researcher, or a blog writer references the project. Ten-line YAML; GitHub auto-generates BibTeX from it on the repo page.SBOM on releases (deferred)
Once CHANGELOG gets a tagged release, each release should carry an SBOM. Two options: (a) GitHub's built-in dependency-graph SBOM export (
gh api repos/:owner/:repo/dependency-graph/sbom) stitched into the release workflow, or (b)anchore/sbom-actionwhich writes SPDX or CycloneDX directly. No code yet → no releases yet → ship this when the first tag does.What to skip (for now)
Keeping this list explicit so future conversations don't re-litigate.
oss-fuzz,cifuzz)Suggested order
Ordered by leverage-per-minute. All of this is non-urgent — ship incrementally, in single-concern PRs that each address one row.
mainwith signed commits + linear history. No files, ~10 minutes, highest leverage..github/dependabot.yml— github-actions ecosystem, weekly, grouped. ~10 minutes..editorconfig— kills PR noise forever. ~5 minutes..github/workflows/shellcheck.yml— immediately useful against the bash inmaya,setup.sh,skills/. ~15 minutes..github/workflows/lint-prose.yml— yamllint + markdownlint + lychee (lychee on schedule, not per-PR). ~30 minutes..github/workflows/codeql.yml— preseed for when code lands. ~10 minutes..github/workflows/gitleaks.yml— with custom patterns for Maya privacy terms sourced fromAGENTS.md. ~30 minutes..github/workflows/scorecard.yml+ README badge. ~15 minutes.CITATION.cff. ~5 minutes.Total: roughly 2.5 hours of focused work, spread across eight to ten small PRs, each independently reviewable.
What ships in the first PR: items 1, 2, 3 (repo settings + dependabot.yml + .editorconfig). It's the smallest coherent unit — three changes, one concern ("turn on the defaults"). Everything after can be its own PR.
How this intersects with issue #1
.github/and repo settings, not the content files Phase 0 is reconciling.shellcheckcatches bash bugs in PR review, secret scanning catches credentials, and branch protection makes the history legible.What this proposal intentionally leaves out
References
permissionsminimization, andharden-runnerGITHUB_TOKENHow to file
Refs: #<this-issue>); the meta-issue's checklist gets checked when the PR merges.#2withRefs: #2(notCloses: #2— Add open source community files and templates #2 is already closed; this is its follow-on).meta,ci,security,good-first-issueon the individual sub-items that are genuinely small (e.g.,.editorconfig,CITATION.cff)..editorconfig) into the same milestone so the guardrails land with (or before) the first real code.