diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..418fa46 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,22 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false + +[*.swift] +indent_style = space +indent_size = 4 + +[*.{yml,yaml}] +indent_style = space +indent_size = 2 + +[*.sh] +indent_style = space +indent_size = 2 diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..3f18bce --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @luzanovdm diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 08508e5..6fa7fd2 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -10,6 +10,7 @@ Describe the user-visible or security-relevant outcome. - [ ] I used only synthetic fixtures and examples. - [ ] I did not add logging, clipboard access, or temporary plaintext files. - [ ] I reviewed subprocess, identity, and atomic-write behavior if this change touches them. +- [ ] I updated `CHANGELOG.md` for a user-visible change, or no entry is needed. ## Screenshots diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e8708ba..8f77570 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,6 +9,10 @@ on: permissions: contents: read +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: test: runs-on: macos-26 @@ -17,9 +21,11 @@ jobs: steps: - name: Check out repository uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 + with: + persist-credentials: false - name: Install test dependencies - run: brew install actionlint age ripgrep shellcheck sops xcodegen + run: brew bundle --file=Brewfile - name: Check shell scripts run: shellcheck Scripts/*.sh diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..b05be37 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,53 @@ +name: CodeQL + +on: + release: + types: + - published + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + analyze: + name: Analyze Swift + runs-on: macos-26 + timeout-minutes: 30 + permissions: + contents: read + security-events: write + + steps: + - name: Check out repository + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7 + with: + persist-credentials: false + + - name: Install build dependencies + run: brew bundle --file=Brewfile + + - name: Generate Xcode project + run: xcodegen generate + + - name: Initialize CodeQL + uses: github/codeql-action/init@7188fc363630916deb702c7fdcf4e481b751f97a # v4 + with: + languages: swift + build-mode: manual + + - name: Build for analysis + run: >- + xcodebuild build + -quiet + -project Cipherleaf.xcodeproj + -scheme Cipherleaf + -destination 'platform=macOS' + -derivedDataPath .build/CodeQLDerivedData + CODE_SIGNING_ALLOWED=NO + + - name: Analyze + uses: github/codeql-action/analyze@7188fc363630916deb702c7fdcf4e481b751f97a # v4 diff --git a/Brewfile b/Brewfile new file mode 100644 index 0000000..458a216 --- /dev/null +++ b/Brewfile @@ -0,0 +1,6 @@ +brew "actionlint" +brew "age" +brew "ripgrep" +brew "shellcheck" +brew "sops" +brew "xcodegen" diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index eaafb97..34f216b 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,10 +1,120 @@ -# Code of conduct +# Contributor Covenant 3.0 Code of Conduct -Be respectful, specific, and constructive. +## Our Pledge -Harassment, discrimination, personal attacks, and publication of another -person's private information are not acceptable. Project maintainers may edit -or remove contributions and restrict participation when necessary to keep the -community safe and productive. +We pledge to make our community welcoming, safe, and equitable for all. -Report conduct concerns privately to the maintainers. +We are committed to fostering an environment that respects and promotes the +dignity, rights, and contributions of all individuals, regardless of +characteristics including race, ethnicity, caste, color, age, physical +characteristics, neurodiversity, disability, sex or gender, gender identity or +expression, sexual orientation, language, philosophy or religion, national or +social origin, socio-economic position, level of education, or other status. +The same privileges of participation are extended to everyone who participates +in good faith and in accordance with this Covenant. + +## Encouraged Behaviors + +While acknowledging differences in social norms, we all strive to meet our +community's expectations for positive behavior. We also understand that our +words and actions may be interpreted differently than we intend based on +culture, background, or native language. + +With these considerations in mind, we agree to behave mindfully toward each +other and act in ways that center our shared values, including: + +1. Respecting the **purpose of our community**, our activities, and our ways of + gathering. +2. Engaging **kindly and honestly** with others. +3. Respecting **different viewpoints** and experiences. +4. **Taking responsibility** for our actions and contributions. +5. Gracefully giving and accepting **constructive feedback**. +6. Committing to **repairing harm** when it occurs. +7. Behaving in other ways that promote and sustain the **well-being of our + community**. + +## Restricted Behaviors + +We agree to restrict the following behaviors in our community. Instances, +threats, and promotion of these behaviors are violations of this Code of +Conduct. + +1. **Harassment.** Violating explicitly expressed boundaries or engaging in + unnecessary personal attention after any clear request to stop. +2. **Character attacks.** Making insulting, demeaning, or pejorative comments + directed at a community member or group of people. +3. **Stereotyping or discrimination.** Characterizing anyone's personality or + behavior on the basis of immutable identities or traits. +4. **Sexualization.** Behaving in a way that would generally be considered + inappropriately intimate in the context or purpose of the community. +5. **Violating confidentiality.** Sharing or acting on someone's personal or + private information without their permission. +6. **Endangerment.** Causing, encouraging, or threatening violence or other + harm toward any person or group. +7. Behaving in other ways that **threaten the well-being** of our community. + +### Other Restrictions + +1. **Misleading identity.** Impersonating someone else for any reason, or + pretending to be someone else to evade enforcement actions. +2. **Failing to credit sources.** Not properly crediting the sources of content + you contribute. +3. **Promotional materials.** Sharing marketing or other commercial content in + a way that is outside the norms of the community. +4. **Irresponsible communication.** Failing to responsibly present content + which includes, links or describes any other restricted behaviors. + +## Reporting an Issue + +Tensions can occur between community members even when they are trying their +best to collaborate. Not every conflict represents a code of conduct violation, +and this Code of Conduct reinforces encouraged behaviors and norms that can +help avoid conflicts and minimize harm. + +When an incident does occur, report it promptly and privately by emailing +[luzanov.dm@gmail.com](mailto:luzanov.dm@gmail.com). Include links or other +context that can help investigate the report. Do not open a public issue. + +The maintainer will take reports seriously and make every effort to respond in +a timely manner. Reports will be investigated using the available messages, +logs, recordings, or witness accounts. Investigations and enforcement actions +will remain as transparent as practical while prioritizing safety and +confidentiality. Enforcement actions are handled privately with the involved +parties, though communicating a mutually agreed resolution to the community +may be appropriate. + +## Addressing and Repairing Harm + +If an investigation finds that this Code of Conduct has been violated, the +following enforcement ladder may be used based on the incident's impact. +Depending on severity, lower steps may be skipped. + +1. **Warning.** A private written warning for a violation, with expectations + for repair such as an apology, acknowledgement of responsibility, or + clarification of expectations. +2. **Temporarily limited activities.** A time-limited cooldown after a repeated + or more serious violation. Limits may apply to particular channels or + interactions. +3. **Temporary suspension.** A suspension with written conditions for return + after repeated violations or a single serious violation. +4. **Permanent ban.** Removal from community spaces when other steps have + failed or a violation makes continued participation unsafe. + +This ladder is a guideline and does not prevent the maintainer from using +reasonable discretion in the community's best interests. + +## Scope + +This Code of Conduct applies within all community spaces and when an individual +is officially representing the community in public or other spaces. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant, version +3.0](https://www.contributor-covenant.org/version/3/0/). + +Contributor Covenant is stewarded by the Organization for Ethical Source and +licensed under [CC BY-SA +4.0](https://creativecommons.org/licenses/by-sa/4.0/). The enforcement ladder +was inspired by the work of [Mozilla's code of conduct +team](https://github.com/mozilla/inclusion). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9b2beb8..5c22a28 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,17 +3,42 @@ Issues and pull requests are welcome. Use synthetic data in every public artifact. +## Before you start + +Search existing issues and pull requests before opening a new one. Small bug +fixes and documentation improvements can go directly to a pull request. Open +an issue before substantial user-interface, security-model, or architecture +changes so the scope can be agreed before implementation. + +Report suspected vulnerabilities through the private process in +[SECURITY.md](SECURITY.md), never in a public issue. + +## Contribution workflow + +1. Fork the repository and create a focused branch from the latest `main`. +2. Make the smallest coherent change and add or update tests where behavior + changes. +3. Run all validation commands below. +4. Open a pull request and complete the template. + +The protected `main` branch accepts changes through pull requests with passing +CI. Maintainers squash-merge accepted changes so each pull request becomes one +signed, reviewable commit. + ## Setup Install Xcode 26 or newer, then: ```sh -brew install actionlint age ripgrep shellcheck sops xcodegen +brew bundle Scripts/test.sh shellcheck Scripts/*.sh actionlint .github/workflows/*.yml ``` +`Brewfile` is the source of truth for command-line development dependencies. +Use `brew bundle check` to confirm that they are already installed. + The generated Xcode project is not committed. Change `project.yml`, regenerate with XcodeGen, and include project-generation coverage in local validation. @@ -60,4 +85,16 @@ encrypted manifest unless all of its public metadata is intentionally public. Keep pull requests focused. Explain the user-visible outcome, security properties affected, and validation performed. UI changes should include a -screenshot made with synthetic values. +screenshot made with synthetic values. Update `CHANGELOG.md` when a change is +visible to users or affects release, compatibility, or security behavior. + +Review feedback is part of the contribution: keep the branch current, answer +questions, and avoid unrelated cleanup in the same pull request. Generated +Xcode projects, build products, signing material, real identities, and real +encrypted documents must not be committed. + +## Licensing + +Cipherleaf does not require a contributor license agreement. By submitting a +contribution, you agree that it is licensed under the repository's +[MIT License](LICENSE). diff --git a/README.md b/README.md index ea98d64..65e254b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # Cipherleaf +[![CI](https://github.com/luzanovdm/cipherleaf/actions/workflows/ci.yml/badge.svg)](https://github.com/luzanovdm/cipherleaf/actions/workflows/ci.yml) +[![CodeQL](https://github.com/luzanovdm/cipherleaf/actions/workflows/codeql.yml/badge.svg)](https://github.com/luzanovdm/cipherleaf/actions/workflows/codeql.yml) + Cipherleaf is a native macOS editor for existing [SOPS](https://github.com/getsops/sops) documents encrypted with native [age](https://github.com/FiloSottile/age) recipients. @@ -58,9 +61,9 @@ brew install age sops ## Run from source ```sh -brew install xcodegen git clone https://github.com/luzanovdm/cipherleaf.git cd cipherleaf +brew bundle xcodegen generate open Cipherleaf.xcodeproj ``` @@ -92,12 +95,15 @@ application fits your threat model. ## Development ```sh -brew install actionlint age ripgrep shellcheck sops xcodegen +brew bundle Scripts/test.sh shellcheck Scripts/*.sh actionlint .github/workflows/*.yml ``` +The repository `Brewfile` is the source of truth for command-line development +and CI dependencies. Run `brew bundle check` to verify an existing setup. + `Scripts/test.sh` runs architecture and security guardrails, strict `swift-format` linting, unit tests, and synthetic SOPS/age integration tests. CI also lints shell scripts and workflows, builds an unsigned review package, diff --git a/SECURITY.md b/SECURITY.md index fb7cf32..8d87888 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,13 +4,25 @@ Please do not open a public issue for a suspected vulnerability. -Use GitHub's private vulnerability reporting feature for this repository. -Include the affected version, a minimal reproduction, and the expected impact. -Do not include real secret values or private age identities. +Use [GitHub's private vulnerability reporting +form](https://github.com/luzanovdm/cipherleaf/security/advisories/new). Include +the affected version, a minimal reproduction, and the expected impact. Do not +include real secret values or private age identities. + +Test only with synthetic data and systems you own or are authorized to use. +Please allow time for investigation and a coordinated fix before public +disclosure. ## Supported versions -Security fixes are applied to the latest release and the default branch. +| Version | Supported | +| --- | --- | +| Latest release | Yes | +| `main` | Yes, as unreleased development code | +| Older releases | No | + +This is a small, volunteer-maintained project. Reports are handled on a +best-effort basis; there is no response-time guarantee or bug bounty program. ## Operational guidance