diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..d8477b7 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,6 @@ +# Public profile, policy, automation, and metadata ownership +* @jay-oraclizer + +/profile/ @jay-oraclizer +/.github/ @jay-oraclizer +/scripts/ @jay-oraclizer diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..cfb832c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Security vulnerability + url: https://github.com/Oraclizer/.github/blob/main/SECURITY.md + about: Use the affected repository's private vulnerability-reporting path. + - name: Support boundary + url: https://github.com/Oraclizer/.github/blob/main/SUPPORT.md + about: Review supported and unsupported request channels. diff --git a/.github/ISSUE_TEMPLATE/documentation.yml b/.github/ISSUE_TEMPLATE/documentation.yml new file mode 100644 index 0000000..06f37db --- /dev/null +++ b/.github/ISSUE_TEMPLATE/documentation.yml @@ -0,0 +1,46 @@ +name: Documentation correction +description: Report a public documentation, link, accessibility, or rendering defect. +title: "[Docs]: " +labels: + - documentation +body: + - type: markdown + attributes: + value: | + Thank you for helping improve Oraclizer's public documentation. Do not include sensitive security details or private repository content. + - type: input + id: repository + attributes: + label: Repository or public page + description: Identify the affected repository or URL. + placeholder: Oraclizer/.github or https://github.com/Oraclizer + validations: + required: true + - type: input + id: location + attributes: + label: Exact location + description: Provide the file, section, anchor, or rendered element. + validations: + required: true + - type: textarea + id: problem + attributes: + label: Problem + description: Explain what is inaccurate, inaccessible, broken, or unclear. + validations: + required: true + - type: textarea + id: correction + attributes: + label: Proposed correction + description: Suggest precise replacement text or behavior if possible. + validations: + required: false + - type: checkboxes + id: safety + attributes: + label: Public-report confirmation + options: + - label: This report contains no vulnerability details, credentials, personal data, private links, or confidential material. + required: true diff --git a/.github/ISSUE_TEMPLATE/repository-surface.yml b/.github/ISSUE_TEMPLATE/repository-surface.yml new file mode 100644 index 0000000..fc24b37 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/repository-surface.yml @@ -0,0 +1,60 @@ +name: Repository surface defect +description: Report a metadata, status, navigation, Community Profile, or repository-setting defect. +title: "[Surface]: " +labels: + - repository-surface +body: + - type: markdown + attributes: + value: | + Use this form for non-sensitive public repository-surface problems. Security reports belong in the private path described by SECURITY.md. + - type: input + id: repository + attributes: + label: Affected repository + placeholder: Oraclizer/.github + validations: + required: true + - type: dropdown + id: surface + attributes: + label: Surface + options: + - About or Topics + - Organization profile + - Community Profile + - Issue or Pull Request template + - Workflow or status check + - Branch or merge setting + - Social preview + - Other public metadata + validations: + required: true + - type: textarea + id: observed + attributes: + label: Observed state + description: Include the public URL and exact current behavior. + validations: + required: true + - type: textarea + id: expected + attributes: + label: Expected state + description: Describe the accurate or intended public behavior. + validations: + required: true + - type: textarea + id: evidence + attributes: + label: Evidence + description: Add non-sensitive screenshots, response codes, or references. + validations: + required: false + - type: checkboxes + id: safety + attributes: + label: Public-report confirmation + options: + - label: This report is non-sensitive and contains no credentials, private repository content, or uncoordinated vulnerability information. + required: true diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..d0ba5f4 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,26 @@ +## Summary + +Describe the smallest reviewable change and link the issue when applicable. + +## Public-surface impact + +- [ ] Organization profile or navigation +- [ ] Repository metadata or social preview +- [ ] Community-health default or contribution route +- [ ] Workflow, ruleset, or repository setting +- [ ] No protocol, proof, implementation, audit, release, or deployment claim changes + +Explain any affected status or assurance boundary: + +## Verification + +- [ ] `node scripts/verify-profile.mjs` +- [ ] `git diff --check` +- [ ] Changed links resolve or an automated-access limitation is recorded +- [ ] Desktop and mobile rendering checked when profile markup or assets change +- [ ] No credentials, private links, internal planning data, or machine-local paths + +## Reviewer focus + +Identify the wording, status boundary, rendering detail, or repository setting +that deserves the closest review. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..a9bb5ce --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly + open-pull-requests-limit: 5 + labels: + - dependencies + - github-actions + commit-message: + prefix: chore(actions) diff --git a/.github/workflows/repository-health.yml b/.github/workflows/repository-health.yml new file mode 100644 index 0000000..67d7bff --- /dev/null +++ b/.github/workflows/repository-health.yml @@ -0,0 +1,29 @@ +name: Repository health + +on: + pull_request: + push: + branches: + - main + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: repository-health-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + profile-health: + name: Profile health + runs-on: ubuntu-24.04 + timeout-minutes: 5 + steps: + - name: Check out repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - name: Verify public repository surface + run: node scripts/verify-profile.mjs diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..f7dfa84 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,43 @@ +# Code of Conduct + +## Our commitment + +Oraclizer is committed to a respectful, harassment-free environment for +technical, academic, standards, and community participation. + +## Expected behavior + +- Challenge claims, proofs, assumptions, and designs with technical specificity. +- Distinguish people from the work under review. +- Accept correction and take responsibility for mistakes. +- Respect disclosure, confidentiality, attribution, and citation boundaries. +- Use inclusive language and make participation accessible where practical. +- Focus discussion on rigorous, reproducible, and constructive outcomes. + +## Unacceptable behavior + +- Harassment, threats, insults, discriminatory comments, or sexualized conduct. +- Trolling, sustained disruption, or bad-faith misrepresentation. +- Publishing private information or vulnerability details without permission. +- Retaliation against a good-faith counterexample or security report. +- Plagiarism, fabricated evidence, or deliberate removal of attribution. + +## Enforcement + +Report conduct concerns privately to `jay@oraclizer.io` with the subject +`ORACLIZER CONDUCT`. Reports will be handled as confidentially as reasonably +possible. Maintainers may edit or remove content, close or lock interactions, +reject contributions, or restrict participation. + +Enforcement should be proportionate and separate from whether a participant's +technical criticism is correct. + +## Scope + +This policy applies in Oraclizer-managed repository spaces and when someone +officially represents Oraclizer in public. It does not govern independent +academic, technical, or standards criticism made without project +representation. + +This policy is adapted from the Contributor Covenant, version 2.1: +https://www.contributor-covenant.org/version/2/1/code_of_conduct.html diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..5d5fdc8 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,51 @@ +# Contributing + +This file provides fallback contribution guidance for Oraclizer repositories +that do not define their own `CONTRIBUTING.md`. Repository-specific guidance +and licenses take precedence. + +## Choose the right channel + +| Contribution | Channel | +| --- | --- | +| Broken link, rendering defect, accessibility problem, or documentation correction | Documentation issue form | +| Repository metadata, public-status, or navigation defect | Repository-surface issue form | +| Material protocol, proof, architecture, or public-claim change | Issue first, before a Pull Request | +| Sensitive or potentially exploitable concern | Private path in `SECURITY.md` | +| Usage or support request | Boundary and routing in `SUPPORT.md` | + +Search existing issues before opening a new one. Keep each issue or Pull +Request to one reviewable concern. + +## Pull Request expectations + +A Pull Request should: + +- explain what changed, why it changed, and which public surface is affected; +- link the review issue when the change is material or claim-affecting; +- distinguish research, specification, implementation, audit, release, and + deployment status; +- include the smallest relevant verification result; +- preserve accessibility, relative links, and responsive rendering; +- contain no credentials, private correspondence, internal planning data, + machine-local paths, generated logs, or unrelated artifacts; +- use the private reporting path for sensitive concerns. + +For this `.github` repository, run: + +```bash +node scripts/verify-profile.mjs +``` + +The check validates repository structure and public-surface invariants. It is +not a substitute for proof, code, deployment, security, or legal review. + +## Contribution rights + +By contributing to this `.github` repository, you represent that you have the +right to submit the material and agree that it may be distributed under the +BSD 3-Clause License. Contributions to another Oraclizer repository remain +subject to that repository's license and contribution policy. + +Opening an issue or Pull Request creates no obligation to accept, merge, +publish, release, or respond within a particular period. diff --git a/GOVERNANCE.md b/GOVERNANCE.md new file mode 100644 index 0000000..cdb5e7b --- /dev/null +++ b/GOVERNANCE.md @@ -0,0 +1,56 @@ +# Governance + +This document governs the public `Oraclizer/.github` repository and the +organization-profile surface it renders. It is not a governance document for +an external protocol, standards body, deployed network, or asset. + +## Maintainer authority + +Oraclizer maintains this repository. Jay Kim (`@jay-oraclizer`) is the current +repository owner and review owner. The maintainer controls access, triage, +merge decisions, public-profile claims, repository settings, and security +coordination. + +Opening an issue or Pull Request creates no obligation to accept, merge, +publish, release, or respond within a particular period. + +## Decision principles + +Changes are evaluated for: + +1. factual consistency with public repositories, specifications, papers, and + standards-process state; +2. explicit separation of research, specification, implementation, audit, + release, and deployment status; +3. accessibility, stable navigation, and responsive rendering; +4. licensing, attribution, disclosure, and confidentiality boundaries; +5. reproducibility of the repository-health check; +6. minimal, reviewable history through Pull Requests. + +## Merge policy + +Changes use a topic branch and Pull Request. The repository-health workflow +must pass, review conversations must be resolved, and the default branch must +retain a linear history. Force pushes and deletion of the default branch are +not permitted. + +A passing check validates repository structure only. It does not establish +the correctness or readiness of any project described by the profile. + +## Tags and releases + +This repository is an organization profile and policy surface, not a packaged +or deployable software product. It therefore does not create routine version +tags or GitHub Releases merely to mark documentation updates. + +If this repository later distributes a versioned artifact, a tag and release +must identify an immutable commit, artifact scope, status, verification, and +change summary. Existing tags must never be moved or reused. + +Visibility changes, protocol versions, paper publication, standards review, +audits, deployments, tags, and releases remain separate decisions. + +## Amendments + +Governance changes use the same Pull Request and review path and remain +traceable in Git history. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8cfd43b --- /dev/null +++ b/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2026, Oraclizer +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..66fa058 --- /dev/null +++ b/README.md @@ -0,0 +1,61 @@ +
+ + + + + Oraclizer + + +### Organization profile and repository defaults + +[**Organization overview**](https://github.com/Oraclizer) · +[**Website**](https://oraclizer.io) · +[**Research**](https://research.oraclizer.io) · +[**Documentation**](https://docs.oraclizer.io) + +[![Repository health](https://github.com/Oraclizer/.github/actions/workflows/repository-health.yml/badge.svg)](https://github.com/Oraclizer/.github/actions/workflows/repository-health.yml) +[![License: BSD-3-Clause](https://img.shields.io/badge/license-BSD--3--Clause-0b5cad.svg)](LICENSE) + +
+ +This public `.github` repository controls two distinct surfaces: + +1. [`profile/README.md`](profile/README.md) is rendered on the public + Oraclizer organization overview. +2. The root community-health files and `.github` templates provide fallback + contribution guidance for Oraclizer repositories that do not define a + repository-specific policy. + +Repository-specific files always take precedence over these defaults. + +## Repository map + +| Path | Purpose | +| --- | --- | +| [`profile/README.md`](profile/README.md) | Public organization profile and project-status map | +| [`profile/assets/`](profile/assets/) | Responsive architecture and social-preview assets | +| [`SECURITY.md`](SECURITY.md) | Coordinated vulnerability-reporting boundary | +| [`CONTRIBUTING.md`](CONTRIBUTING.md) | Default contribution and review expectations | +| [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md) | Participation and enforcement expectations | +| [`SUPPORT.md`](SUPPORT.md) | Support, issue, and security channel separation | +| [`GOVERNANCE.md`](GOVERNANCE.md) | Maintenance, merge, and release policy for this repository | +| [`.github/`](.github/) | CODEOWNERS, issue forms, Pull Request template, Dependabot, and Continuous Integration | +| [`scripts/verify-profile.mjs`](scripts/verify-profile.mjs) | Dependency-free public-surface verification | + +## Public-surface contract + +Changes must keep repository visibility, protocol status, research status, +assurance boundaries, and links consistent with the underlying public +artifacts. A green repository-health check validates the structure of this +surface; it does not establish a deployment, audit, legal conclusion, +operational-security claim, or model-to-code refinement. + +Read [CONTRIBUTING.md](CONTRIBUTING.md) before proposing a change. Report +sensitive concerns through [SECURITY.md](SECURITY.md), never through a public +issue or Pull Request. + +## License + +The files in this repository are licensed under the +[BSD 3-Clause License](LICENSE). A repository that inherits community-health +guidance from here remains governed by its own license. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..cfd148f --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,42 @@ +# Security policy + +This file is the fallback security policy for Oraclizer repositories that do +not define a repository-specific `SECURITY.md`. A policy in the affected +repository takes precedence. + +## Report sensitive concerns privately + +For the repository affected by the concern: + +1. Open its **Security** tab. +2. Select **Advisories**. +3. Select **Report a vulnerability**. + +If Private Vulnerability Reporting is unavailable, email +`jay@oraclizer.io` with the subject `ORACLIZER SECURITY`. Identify the affected +repository and exact commit. Do not include unrelated secrets, personal data, +production credentials, or confidential third-party material. + +Do not disclose exploit details in a public issue, Pull Request, discussion, +standards forum, research review, or social post before coordinated disclosure. + +## Public reports + +Broken links, documentation defects, reproducibility failures, overly strong +claims, non-sensitive counterexamples, and model-scope concerns may use the +affected repository's public issue forms. + +When possible, include the exact repository, commit, path, tool version, +minimal reproduction, expected result, and observed result. + +## Handling boundary + +The maintainer will assess scope and may request additional information. No +response time, remediation time, disclosure date, bounty, safe-harbor term, +financial reward, audit conclusion, or service-level commitment is promised by +this policy. + +A public repository or passing workflow does not establish the security of an +implementation, deployment, network, cryptographic system, legal process, or +modified fork. The affected repository's license and explicit assurance +boundary remain controlling. diff --git a/SUPPORT.md b/SUPPORT.md new file mode 100644 index 0000000..341a31d --- /dev/null +++ b/SUPPORT.md @@ -0,0 +1,24 @@ +# Support + +Oraclizer's public repositories provide research, specifications, source, +formal artifacts, and repository-specific review channels. They do not provide +production support, integration consulting, deployment certification, asset +recovery, incident response, legal advice, or a response-time agreement. + +## Where to go + +| Need | Channel | +| --- | --- | +| Organization profile or public-link defect | Issue form in `Oraclizer/.github` | +| Repository-specific bug, proof, or documentation question | The affected repository's issue forms and `CONTRIBUTING.md` | +| Protocol semantics and conformance scope | [OIP documentation](https://docs.oraclizer.io/oip-v05/oip-overview/) | +| Research paper or artifact | [Research index](https://research.oraclizer.io) and the linked repository | +| Sensitive vulnerability | Private path in the affected repository's `SECURITY.md` | +| General or research inquiry | `jay@oraclizer.io` | + +Search existing public material first and include the exact repository, +commit, version, and reproduction details where applicable. Maintainers may +redirect, close, or leave unanswered requests outside the published scope. + +Never post credentials, personal data, confidential production details, or +uncoordinated vulnerability information in a public support channel. diff --git a/profile/assets/oraclizer-social-preview.png b/profile/assets/oraclizer-social-preview.png new file mode 100644 index 0000000..309fca7 Binary files /dev/null and b/profile/assets/oraclizer-social-preview.png differ diff --git a/profile/assets/oraclizer-social-preview.svg b/profile/assets/oraclizer-social-preview.svg new file mode 100644 index 0000000..a1b7d78 --- /dev/null +++ b/profile/assets/oraclizer-social-preview.svg @@ -0,0 +1,47 @@ + + Oraclizer organization profile social preview + Oraclizer wordmark with the statement Formal, protocol, and proving foundations for cross-domain state synchronization and three labeled focus areas. + + + + + + + + + + + + + + + + + + + + + Cross-domain state synchronization + Formal, protocol, and proving foundations with explicit assurance boundaries. + + + + + PROTOCOL + OIP · RCP · ERC-8319 + + + + + FORMAL + Isabelle/HOL artifacts + + + + + PROVING + StateSync-GKR in development + + + ORACLIZER.IO + diff --git a/scripts/verify-profile.mjs b/scripts/verify-profile.mjs new file mode 100644 index 0000000..0f99bea --- /dev/null +++ b/scripts/verify-profile.mjs @@ -0,0 +1,163 @@ +import { existsSync, readFileSync } from "node:fs"; +import { dirname, normalize, resolve } from "node:path"; + +const root = process.cwd(); +const failures = []; + +function fail(message) { + failures.push(message); +} + +function read(relativePath) { + const absolutePath = resolve(root, relativePath); + if (!existsSync(absolutePath)) { + fail(`Missing required file: ${relativePath}`); + return ""; + } + const content = readFileSync(absolutePath, "utf8"); + if (content.startsWith("\uFEFF")) fail(`UTF-8 BOM is not allowed: ${relativePath}`); + if (content.includes("\uFFFD")) fail(`Replacement character found: ${relativePath}`); + return content; +} + +const requiredFiles = [ + "README.md", + "LICENSE", + "SECURITY.md", + "CONTRIBUTING.md", + "CODE_OF_CONDUCT.md", + "SUPPORT.md", + "GOVERNANCE.md", + "profile/README.md", + "profile/assets/oraclizer-system-map.svg", + "profile/assets/oraclizer-system-map-mobile.svg", + "profile/assets/oraclizer-social-preview.svg", + ".github/CODEOWNERS", + ".github/PULL_REQUEST_TEMPLATE.md", + ".github/ISSUE_TEMPLATE/config.yml", + ".github/ISSUE_TEMPLATE/documentation.yml", + ".github/ISSUE_TEMPLATE/repository-surface.yml", + ".github/dependabot.yml", + ".github/workflows/repository-health.yml", +]; + +for (const file of requiredFiles) read(file); + +const requiredBinaryFiles = ["profile/assets/oraclizer-social-preview.png"]; +for (const file of requiredBinaryFiles) { + if (!existsSync(resolve(root, file))) fail(`Missing required file: ${file}`); +} + +const profile = read("profile/README.md"); +const requiredProfileText = [ + "Formal, protocol, and proving foundations for cross-domain state synchronization", + "System and research map", + "Repository portfolio", + "Preparing for public release", + "Protocols and standards", + "Published research", + "Review and contact", + "Typed Regulatory Uniformity for Security Tokens", + "Unaudited and not for production", +]; + +for (const text of requiredProfileText) { + if (!profile.includes(text)) fail(`Profile is missing required text: ${text}`); +} + +const forbiddenPatterns = [ + [/Total Regulatory Unified/i, "stale ERC-TRUST expansion"], + [/The first oracle/i, "unverifiable first claim"], + [/complete state/i, "overbroad complete-state claim"], + [/safety and liveness under Byzantine faults/i, "unsupported Byzantine liveness claim"], + [/github\.com\/Oraclizer\/(?:erc-trust|statesync-gkr)/i, "private repository link"], + [/[A-Za-z]:\\Users\\/i, "machine-local Windows path"], +]; + +const publicTextFiles = [ + "README.md", + "SECURITY.md", + "CONTRIBUTING.md", + "CODE_OF_CONDUCT.md", + "SUPPORT.md", + "GOVERNANCE.md", + "profile/README.md", +].map((file) => [file, read(file)]); + +for (const [file, content] of publicTextFiles) { + for (const [pattern, description] of forbiddenPatterns) { + if (pattern.test(content)) fail(`${file} contains ${description}`); + } +} + +function verifyRelativeTargets(markdownPath, markdown) { + const targets = []; + for (const match of markdown.matchAll(/\[[^\]]*\]\(([^)]+)\)/g)) targets.push(match[1]); + for (const match of markdown.matchAll(/(?:src|srcset)="([^"]+)"/g)) targets.push(match[1]); + + for (const rawTarget of targets) { + const target = rawTarget.trim().split(/\s+/)[0]; + if (/^(?:https?:|mailto:|#)/i.test(target)) continue; + const withoutFragment = target.split("#")[0].split("?")[0]; + if (!withoutFragment) continue; + const candidate = normalize(resolve(root, dirname(markdownPath), withoutFragment)); + if (!candidate.startsWith(root)) { + fail(`${markdownPath} escapes the repository: ${target}`); + } else if (!existsSync(candidate)) { + fail(`${markdownPath} has a missing relative target: ${target}`); + } + } +} + +verifyRelativeTargets("README.md", read("README.md")); +verifyRelativeTargets("profile/README.md", profile); + +for (const svgPath of [ + "profile/assets/oraclizer-system-map.svg", + "profile/assets/oraclizer-system-map-mobile.svg", + "profile/assets/oraclizer-social-preview.svg", +]) { + const svg = read(svgPath); + if (!/^`); + if (!/]*>[^<]+<\/title>/.test(svg)) fail(`${svgPath} needs a non-empty title`); + if (!/]*>[^<]+<\/desc>/.test(svg)) fail(`${svgPath} needs a non-empty description`); + if (!/viewBox="0 0 \d+ \d+"/.test(svg)) fail(`${svgPath} needs a numeric viewBox`); + if (/= 1_000_000) fail("Social preview must remain under 1 MB"); + +const workflow = read(".github/workflows/repository-health.yml"); +const checkout = workflow.match(/actions\/checkout@([^\s#]+)/)?.[1] ?? ""; +if (!/^[0-9a-f]{40}$/.test(checkout)) { + fail("actions/checkout must be pinned to a full 40-character commit SHA"); +} +if (!workflow.includes("permissions:\n contents: read")) { + fail("Repository-health workflow must use read-only contents permission"); +} +if (!workflow.includes("timeout-minutes:")) { + fail("Repository-health workflow must define a timeout"); +} + +if (failures.length > 0) { + console.error("Repository health checks failed:"); + for (const failure of failures) console.error(`- ${failure}`); + process.exit(1); +} + +console.log( + `Repository health checks passed (${requiredFiles.length + requiredBinaryFiles.length} required files).`, +);