- Shell 72.4%
- Rust 27.6%
| rust | ||
| scripts | ||
| .editorconfig | ||
| .gitignore | ||
| bash.md | ||
| frontend.md | ||
| LICENSE | ||
| privacy.md | ||
| python.md | ||
| README.md | ||
| rust.md | ||
| SECURITY.md.example | ||
Femboy Cyber Networks coding guidelines
These documents describe how we design, write, and review code across femboyisp's projects — network services, tooling, and the occasional frontend. They exist so that decisions don't have to be re-litigated on every PR, and so a new contributor (human or AI) can pick up the same conventions everyone else follows.
This is a living document. If something here stops making sense for how the team actually works, change it — but change the doc, don't just quietly ignore it.
Complexity, edge cases, and problem scope
When implementing a feature, resist the urge to solve for every hypothetical case up front. Make the common path simple and correct, and let genuinely unlikely scenarios fail loudly (an error, a panic in debug builds) rather than adding branches to handle them "just in case."
Don't generalize before you need to. If you're writing a function that
allows traffic from a specific source, call it what it does —
allow_lan_subnet() — rather than building a generic
create_rule(Action, Subject) abstraction before a second caller actually
needs it. Reuse that justifies the added complexity should come from a real
second use case, not a predicted one.
Code quality and documentation
Leave code in an equally good or better state than you found it. That doesn't mean unrelated refactoring in every PR — it means not adding a second undocumented, tangled function next to an existing one just because "that's how the file already looks."
What to document
Comments should add information the code doesn't already express. A comment that restates the function signature in prose is dead weight — remove it or replace it with the thing the signature can't tell the reader:
/// Spawns `command` as a subprocess. Dropping the returned handle
/// does NOT kill the child process — call `.kill()` explicitly.
/// `stdin`/`stdout`/`stderr` are all inherited from the parent.
fn spawn_cmd(command: String) -> CmdHandle
The first line restating "spawns a subprocess" would be useless. The ownership/lifetime behavior and stdio wiring are not obvious from the signature — that's what's worth writing down.
Code review and PR process
Femboy is currently a small team, sometimes a solo effort on a given repo. The review process should scale to that reality without dropping the parts that actually catch bugs.
- Solo work: before merging your own change, do a self-review pass on the diff as if you were reviewing someone else's PR — re-read it fresh, not from memory of writing it. Write a PR description that explains why, not just what changed.
- With a second person available: assign a reviewer who's familiar with the part of the code being touched. It's fine to ask for early feedback on a proof of concept before a full implementation, to avoid a large PR built on an approach the reviewer would have pushed back on.
- Always get a second reviewer, regardless of team size, for changes to
cryptographic code, authentication/authorization, parsing of untrusted
network input, or firewall/routing rule generation. See
privacy.md. If no second person is available, treat this as a blocker to ship, not something to skip. - Mark work-in-progress PRs as drafts (or a WIP label) if you want early feedback on unfinished code — don't let an unfinished PR sit ambiguously.
Code formatting
See .editorconfig for the enforced baseline. In summary:
- UTF-8 encoding, no BOM.
- Files end with a newline.
- No trailing whitespace on any line.
- LF (
\n) line endings only — configure git to convert on checkout if your OS needs CRLF locally, but never commit CRLF. - Indent with spaces, except where a language's ecosystem customarily uses
tabs (e.g.
Makefiles).
Variable naming
Variables that represent filesystem paths follow a consistent suffix so the reader doesn't have to guess what a value actually holds:
foo_path— a path to a file, absolute or relative (/tmp/lol.data,./output.log).foo_dir— a path to a directory (/tmp,../foo/bar). Don't end the value with a trailing separator.foo_filename— a bare filename, not a path (foo.log), usually combined with a_dirto build a path.foo_dirname— a bare directory name, not a path.
If a variable holds only a fragment of a path or a template that resolves to
one (".exe", "/var/log/app.{}.log"), suffix it with prefix, suffix, or
template instead.
Language-specific guidelines
Privacy and security
Femboy is a privacy-focused company — that has to show up in the code, not
just the marketing copy. See privacy.md for data
minimization, logging discipline, secrets handling, and dependency vetting.
SECURITY.md.example is a template repos can copy for
their own vulnerability-reporting policy.
Git
Commit messages
For repos containing code (Rust, Python, Bash, frontend projects): follow the standard imperative-mood convention —
- Capitalize the subject line.
- Don't end the subject line with a period.
- Use the imperative mood ("Add", "Fix", "Increase" — not "Added", "Fixes", "Increased").
- Keep the subject line under ~72 characters.
- Separate subject from body with a blank line if you need a body.
Docs-only or personal-lab repos (e.g. CastleTCP) are explicitly exempt —
keep whatever tone already exists there rather than retrofitting a formal
style onto casual, personal documentation.
Branch naming
Kebab-case, lowercase: add-links-to-readme, fix-linux-lan-route-parsing.
Describe what's being done without extra verbosity — fix-routing-table is
less useful than fix-linux-lan-route-parsing. Keep exact external
identifiers (CVE numbers, ticket IDs) in their canonical casing if changing
it would make them harder to recognize.
Changelogs
Keep a changelog for every project that ships something reusable (a service, a library, a CLI) following Keep a Changelog:
- Categories in order: Added, Changed, Deprecated, Removed, Fixed, Security.
- Write entries in the imperative mood, matching commit message style.
- Only list what changed since the last release — if something was added and then modified within the same unreleased period, merge them into one entry describing the net effect.
Dead code
Don't leave unused code around "in case it's needed later." It adds surface area for a reader to wonder about and maintain. If you're adding code now that a follow-up PR (arriving soon) will use, that's fine — but justify it in the PR description or a comment, and don't let it linger past that follow-up.