mirror of
https://github.com/forkless/NotAlterra.git
synced 2026-08-18 01:09:20 +02:00
add reusable project skills (6 agnostic, 2 project-specific)
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
# CI/CD Pipeline Setup
|
||||
|
||||
Blueprint for setting up a GitHub Actions CI/CD pipeline with checks,
|
||||
builds, draft releases, and supply-chain provenance.
|
||||
|
||||
## Overview
|
||||
|
||||
The pipeline is organized as a single workflow file (`.github/workflows/ci.yml`)
|
||||
with jobs that run in dependency order. Tag pushes trigger the build+release
|
||||
path; branch pushes and PRs trigger only the check path.
|
||||
|
||||
## Job Structure
|
||||
|
||||
```
|
||||
check (every push)
|
||||
├── unit tests
|
||||
├── linter
|
||||
├── dependency audit
|
||||
└── documentation
|
||||
│
|
||||
pages (master only) — deploy API docs
|
||||
│
|
||||
build (tags only)
|
||||
├── compile for all targets
|
||||
├── package into archives
|
||||
└── upload as workflow artifacts
|
||||
│
|
||||
provenance (tags only) — SLSA attestation
|
||||
│
|
||||
release (tags only) — create draft release with all artifacts
|
||||
```
|
||||
|
||||
## Check Job
|
||||
|
||||
Runs on every push and pull request. Should include:
|
||||
|
||||
- **Check** — verify the project compiles
|
||||
- **Tests** — run the full test suite
|
||||
- **Linter** — enforce zero warnings
|
||||
- **Dependency audit** — check for known vulnerabilities
|
||||
- **Documentation** — generate and upload API docs (master only)
|
||||
|
||||
```yaml
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- run: cargo check --workspace
|
||||
- run: cargo test --workspace
|
||||
- run: cargo clippy --workspace -- -D warnings
|
||||
- run: cargo doc --no-deps
|
||||
```
|
||||
|
||||
## Build & Release Job
|
||||
|
||||
Only runs on tag pushes matching a version pattern (e.g. `v*`).
|
||||
|
||||
- Builds for all target platforms
|
||||
- Creates release archives (tar.gz, zip)
|
||||
- Generates SHA256 hashes of all artifacts
|
||||
- Uploads archives as workflow artifacts
|
||||
- Sets `draft: true` so releases require manual publishing
|
||||
|
||||
```yaml
|
||||
build:
|
||||
needs: check
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
outputs:
|
||||
hashes: ${{ steps.hash.outputs.hashes }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- run: <build commands for each target>
|
||||
- name: Package
|
||||
run: <create archives>
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
path: builds/
|
||||
```
|
||||
|
||||
## Provenance (SLSA)
|
||||
|
||||
Uses the SLSA v3 generator to attest that release artifacts were built
|
||||
by the CI pipeline from a specific commit.
|
||||
|
||||
```yaml
|
||||
provenance:
|
||||
needs: build
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0
|
||||
with:
|
||||
base64-subjects: "${{ needs.build.outputs.hashes }}"
|
||||
upload-assets: false
|
||||
```
|
||||
|
||||
## Draft Release Job
|
||||
|
||||
Creates a draft release after build + provenance both complete. Downloads
|
||||
the binary artifacts and provenance attestation, then uploads them together.
|
||||
|
||||
```yaml
|
||||
release:
|
||||
needs: [build, provenance]
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
steps:
|
||||
- uses: actions/download-artifact@v4
|
||||
- uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: <artifact paths>
|
||||
body_path: _release.md
|
||||
draft: true
|
||||
```
|
||||
|
||||
## Guardrails
|
||||
|
||||
- Releases are always **drafts** — the maintainer tests before publishing
|
||||
- Provenance runs as a separate job to avoid interfering with the release
|
||||
- `upload-assets: false` on the SLSA generator — let the release job handle all uploads
|
||||
- SHA256 hashes are generated in the build job and passed to provenance
|
||||
|
||||
## Key Actions
|
||||
|
||||
| Action | Purpose |
|
||||
|--------|---------|
|
||||
| `actions/checkout@v4` | Check out source code |
|
||||
| `actions/upload-artifact@v4` | Store build artifacts between jobs |
|
||||
| `actions/download-artifact@v4` | Retrieve artifacts in downstream jobs |
|
||||
| `softprops/action-gh-release@v2` | Create releases (supports `draft: true`) |
|
||||
| `slsa-framework/slsa-github-generator` | Generate SLSA v3 provenance |
|
||||
| `dtolnay/rust-toolchain@stable` | Install the language toolchain |
|
||||
|
||||
## First-Time Setup
|
||||
|
||||
1. Create `.github/workflows/ci.yml` with the job structure above
|
||||
2. Create `_release.md` with the initial release notes template
|
||||
3. Enable GitHub Pages if using API docs (Settings → Pages → GitHub Actions)
|
||||
4. Create a signed tag and push to verify the pipeline
|
||||
5. Test the draft → publish cycle end-to-end
|
||||
@@ -0,0 +1,50 @@
|
||||
# Documentation
|
||||
|
||||
When to update each documentation file in the project.
|
||||
|
||||
## Hierarchy
|
||||
|
||||
| File | Purpose | When to update |
|
||||
|------|---------|----------------|
|
||||
| `src/*` | Doc comments on every function | Every change to the function |
|
||||
| `CHANGELOG.md` | What changed, version, date | Every commit |
|
||||
| `GOVERNANCE.md` | Roadmap, release process, checklist | When process or plans change |
|
||||
| `KNOWN_ISSUES.md` | Bugs and limitations users might encounter | When a new issue surfaces or is resolved |
|
||||
| `DECISIONS.md` | Rationale behind architecture choices | When a significant decision is made |
|
||||
| `_release.md` | What's new in the current release | Every release |
|
||||
| `README.md` | User-facing features, build instructions | When features or setup change |
|
||||
| CI workflow file | Pipeline configuration | When pipeline logic changes |
|
||||
|
||||
## Doc Comment Standards
|
||||
|
||||
- Every public function must have a doc comment
|
||||
- Each comment explains *what* the function does, *why* it exists, and
|
||||
*what edge cases* it handles
|
||||
- No "Internal helper" or "see module-level docs" placeholders
|
||||
- Language-standard doc format (e.g. `///` in Rust, `///` in C#, `/** */` in JS)
|
||||
|
||||
## Changelog Format
|
||||
|
||||
```
|
||||
## [v0.x.y] — YYYY-MM-DD
|
||||
|
||||
### Added
|
||||
- New features
|
||||
|
||||
### Fixed
|
||||
- Bug fixes
|
||||
|
||||
### Changed
|
||||
- Behavior changes, refactors
|
||||
|
||||
### Removed
|
||||
- Features removed
|
||||
|
||||
### Notes
|
||||
- Operational notes (git resets, CI issues, etc.)
|
||||
```
|
||||
|
||||
## Release Notes
|
||||
|
||||
- Contains only the current version's changes — no history from older versions
|
||||
- Replaced entirely for each new release, not appended
|
||||
@@ -0,0 +1,29 @@
|
||||
# Privacy & Security
|
||||
|
||||
Privacy-first design principles and security practices.
|
||||
|
||||
## Privacy Principles
|
||||
|
||||
- **No sensitive paths written to disk** — user data is session-only when possible
|
||||
- **No scanning of user profiles or system directories** beyond the current user
|
||||
- **All logged paths sanitized** to strip user-identifiable prefixes
|
||||
- **User consent tracked via sentinel file**, not a config file with user data
|
||||
|
||||
## Input Handling
|
||||
|
||||
- Strip control characters from user-provided input before it reaches
|
||||
config files, logs, or the filesystem — prevents injection and log forgery
|
||||
- Validate and sanitize all external input before processing
|
||||
|
||||
## Security Practices
|
||||
|
||||
- `deny(unsafe_code)` enabled where the language supports it — zero unsafe
|
||||
- Dependency auditing and license checks in CI for every commit
|
||||
- GPG-signed release tags with build provenance attestation
|
||||
- Vulnerability disclosure policy documented in the repository
|
||||
|
||||
## What We Avoid
|
||||
|
||||
- No telemetry, no network connections, no auto-updater
|
||||
- No admin or root privileges required — runs in user context
|
||||
- No third-party services in the shipped binary
|
||||
@@ -0,0 +1,53 @@
|
||||
# Release Workflow
|
||||
|
||||
Versioning, release checklist, signing, and push conventions.
|
||||
|
||||
## Versioning
|
||||
|
||||
| Bump | When | Example |
|
||||
|------|------|---------|
|
||||
| PATCH | Bug fix or small polish after a release | v0.3.1 → v0.3.2 |
|
||||
| MINOR | New feature or significant restructure | v0.3.x → v0.4.0 |
|
||||
| MAJOR | Breaking change (1.0+ only) | 1.0.0 → 2.0.0 |
|
||||
|
||||
- Version in the project manifest matches the latest release tag
|
||||
- Tags are created at release time, not per-commit
|
||||
- Multiple commits can happen between tags
|
||||
|
||||
## Draft Release Cycle
|
||||
|
||||
```
|
||||
commit → push → tag v0.x.y → CI builds draft → user tests → publish
|
||||
```
|
||||
|
||||
No release goes live without the user testing the draft first.
|
||||
|
||||
## Release Checklist
|
||||
|
||||
Before signing a release tag:
|
||||
|
||||
- [ ] Impact analysis completed — all call sites for new/changed functions
|
||||
- [ ] All tests pass
|
||||
- [ ] Linter passes with zero warnings
|
||||
- [ ] CHANGELOG.md has an entry for the new version
|
||||
- [ ] Working tree is clean — no uncommitted changes
|
||||
- [ ] Release notes file is updated for the new version
|
||||
|
||||
After CI completes:
|
||||
|
||||
- [ ] Download draft binaries from the releases page
|
||||
- [ ] Test on target platform — basic workflow, key features
|
||||
- [ ] Click **Publish release** on the hosting platform when satisfied
|
||||
|
||||
## Signing & Push
|
||||
|
||||
- Commit with `--no-gpg-sign` (avoids GPG passphrase hang in non-interactive terminals)
|
||||
- Maintainer amends with `--gpg-sign` before push
|
||||
- Normal push for fast-forward commits
|
||||
- `--force-with-lease` for amended commits or tag refreshes
|
||||
- If force-pushing, delete old tag and re-tag after the new commit lands
|
||||
|
||||
## Release Notes
|
||||
|
||||
- Release notes file contains only the current version's changes
|
||||
- Historical release notes on the platform are cleaned per-release
|
||||
@@ -0,0 +1,78 @@
|
||||
# Rust Standards
|
||||
|
||||
Coding conventions and patterns for the NotAlterra project.
|
||||
|
||||
## Error Handling
|
||||
|
||||
- Use `anyhow::Result` for fallible functions — no custom error types
|
||||
- `anyhow::bail!` for early returns with context
|
||||
- `.with_context(|| format!(...))` on `Result` from external crates
|
||||
- Avoid `unwrap()` and `expect()` outside of tests and examples
|
||||
- Use `let _ = fallible_fn()` when deliberately ignoring errors
|
||||
|
||||
## File I/O
|
||||
|
||||
- Prefer `std::fs` convenience functions for simple operations
|
||||
(`fs::read()`, `fs::write()`, `fs::read_dir()`)
|
||||
- Use `PathBuf` for owned paths, `&Path` for borrowed references
|
||||
- Validate paths early with `path.exists()` before operations
|
||||
- Use `saturating_sub` for all arithmetic that could underflow
|
||||
|
||||
## String Handling
|
||||
|
||||
- Use `format!()` for construction, avoid `+` concatenation
|
||||
- Use `to_string_lossy()` for OsStr → String conversion
|
||||
- Strip control characters from user input before storage or logging
|
||||
|
||||
## Data Structures
|
||||
|
||||
- Prefer `Vec` over linked lists or custom containers
|
||||
- Use `HashSet` for deduplication
|
||||
- Use `Option<T>` for nullable values — never `null` or sentinel values
|
||||
- Use `struct` with named fields for complex return types
|
||||
- Derive `Debug, Clone` on all data structures, `Default` where meaningful
|
||||
|
||||
## Pattern: Property Extraction (GVAS parser)
|
||||
|
||||
All four extractors follow the same pattern:
|
||||
1. Scan for property name using `windows(target.len()).position()`
|
||||
2. Validate the FName header (length dword + null terminator)
|
||||
3. Skip past the property type name
|
||||
4. Validate bounds before every index access
|
||||
5. Return `Option` or `Result` — never panic
|
||||
|
||||
When adding a new property type, follow this exact pattern and add a bounds
|
||||
check on every array access.
|
||||
|
||||
## Pattern: TUI Dialogs
|
||||
|
||||
All dialogs follow the same structure:
|
||||
1. Define popup area with `centered_rect_size()` or `centered_rect()`
|
||||
2. Render `Clear` widget, then a bordered `Block`
|
||||
3. Compute `inner` area with margin
|
||||
4. Render title, body, buttons in sequence
|
||||
5. Call `draw_whale_separator(f, bar, app)` at the bottom
|
||||
|
||||
## Pattern: Menu Actions
|
||||
|
||||
All menu actions:
|
||||
1. Validate preconditions (save folder set, backup exists)
|
||||
2. Show status/spinner if the operation takes time
|
||||
3. Call through to `ops::*` for actual file operations
|
||||
4. Log via `guard::log_action()` with sanitized paths
|
||||
5. Show result dialog (success or error)
|
||||
6. Refresh dashboard stats
|
||||
|
||||
## Clippy
|
||||
|
||||
- `-D warnings` enforced in CI — no exceptions
|
||||
- Fix lints immediately when CI catches new ones
|
||||
- Common lints that have fired: `collapsible_match`, `manual_is_multiple_of`,
|
||||
`empty_line_after_doc_comments`, `needless_borrows_for_generic_args`
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Prefer crates with 50M+ downloads for core functionality
|
||||
- Avoid platform-specific FFI — prefer pure Rust where possible
|
||||
- Keep dependency count minimal — each new crate is a review point
|
||||
- Run `cargo audit` and `cargo deny` before each release
|
||||
@@ -0,0 +1,23 @@
|
||||
# Session Protocol
|
||||
|
||||
How to structure and execute each development session efficiently.
|
||||
|
||||
## Initialization
|
||||
|
||||
1. **Full project scan first** — read the build file, all source files,
|
||||
tests, docs. Ensures the full codebase is understood before making changes.
|
||||
2. **Check version control status** — identify any uncommitted work from
|
||||
prior sessions.
|
||||
3. **Load companion skills** — `documentation`, `release-workflow`,
|
||||
`testing-fuzzing`, `privacy-security`, `ci-cd-pipeline`.
|
||||
|
||||
## Task Protocol
|
||||
|
||||
1. **Impact analysis before code** — list every file and call site that needs
|
||||
to change. Present for validation before writing code.
|
||||
2. **One feature per cycle** — one logical change per commit. Batch docs,
|
||||
changelog, and version metadata with the feature.
|
||||
3. **Call site audit on completion** — verify every reference is updated.
|
||||
Build + test + lint before declaring done.
|
||||
4. **Draft release cycle** — commit → push → tag → CI builds draft →
|
||||
user tests → publish. Never ship without draft testing.
|
||||
@@ -0,0 +1,37 @@
|
||||
# Testing & Fuzzing
|
||||
|
||||
Testing conventions and fuzzing strategy.
|
||||
|
||||
## Integration Tests
|
||||
|
||||
**Test patterns to follow:**
|
||||
- Use temporary directories for all file-based tests
|
||||
- Test both success and failure paths
|
||||
- Test round-trips: create → process → verify content matches
|
||||
- Test edge cases: empty inputs, truncated data, missing files
|
||||
|
||||
**Where tests live:**
|
||||
- `tests/` — cross-module integration tests
|
||||
- `src/` — unit tests in language-standard test modules
|
||||
- `fuzz/fuzz_targets/` — fuzz targets
|
||||
|
||||
## Fuzz Targets
|
||||
|
||||
Fuzzing is for code that parses **untrusted binary input**.
|
||||
|
||||
**When to add a fuzz target:**
|
||||
- Custom binary format parsers
|
||||
- Archive round-trips (create archive from fuzzed inputs → restore → compare)
|
||||
- Not needed for deterministic operations or wrapping established libraries
|
||||
|
||||
**Requirements:**
|
||||
- Fuzzing requires a nightly toolchain for sanitizer instrumentation
|
||||
- The project must have a fuzz harness (e.g. cargo-fuzz, libfuzzer, oss-fuzz)
|
||||
|
||||
## Coverage Requirements
|
||||
|
||||
- Every new feature ships with integration or unit tests
|
||||
- Fuzz targets for binary parsers and archive round-trips only
|
||||
- All tests must pass before every commit
|
||||
- Linter must pass with zero warnings
|
||||
- Doc coverage check must pass (if implemented)
|
||||
Reference in New Issue
Block a user