Propose a Design
Once a feature issue is refined and assigned to you, create a design discussion to propose how you'll solve it.
Go to GitHub Discussions, select the "Design" category, and outline your high-level approach to solving the assigned problem.
Open Design Discussion →The community will ask clarifying questions, identify edge cases, and suggest alternatives. Respond promptly and be open to feedback. Most discussions reach clarity within 1 to 2 weeks.
Maintainers formally review the proposal. The outcome is one of:
Write the agreed design up as a specification and a threat model, then add both to the repository through a pull request. Reviewers work through the detail here, on the design, before any code exists.
What to submit →Once the specification is merged, you (or someone else) can implement the feature. You are credited as the design author regardless.
See Contribute Code →Review Outcomes
| Outcome | Meaning | Next step |
|---|---|---|
| ✅ Approved | Design is sound | Write the specification and threat model |
| 🔄 Needs Revision | Good direction, changes needed | Address feedback, iterate (typically 1 to 2 cycles) |
| ❌ Rejected | Fundamental issues found | Maintainer explains; discussion closed with documentation |
Rejection is not a reflection on you. It's how the process protects the codebase. Better to catch issues during design than implementation.
Specification and Threat Model
The design discussion settles the approach. The specification and the threat model record it in the repository, under docs-internals/, where reviewers can comment on the detail line by line and where the next contributor can find it later.
When the documents are required
Both documents are required before development begins for:
- a refined feature issue labeled
Type/New Feature, - a major improvement labeled
Type/Improvementthat changes behavior, APIs, database schema, or a trust boundary, - a refactor that moves ownership boundaries between components, or changes an existing seam.
They are not required for bug fixes, documentation changes, dependency updates, test-only changes, or an improvement that stays inside a single component without changing its contract.
If you are unsure which side of the line your change falls on, ask in the design discussion. A maintainer will tell you whether the documents are needed.
What each document covers
Start from the templates in the repository, and remove every template instruction before you submit.
| Document | Covers |
|---|---|
| spec.md | The feature: summary, architecture, detailed design, and the requirements with their acceptance criteria. Sections for the data model, API, UI, and configuration are conditional. |
| threat-model.md | The security posture: trust boundaries, actors and their entitlements, each interaction and its data flow, a threat assessment per interaction, and the security review checklist. |
Where the documents live
Create one directory per feature under docs-internals/, named after the feature area in kebab-case:
docs-internals/ldap-user-sync/
├── spec.md
├── threat-model.md
└── assets/
Keep mockups and diagrams in assets/, and reference them with a relative path such as assets/login-screen.png. The specification asks for a mockup of every new or changed screen.
Before you submit
Check that:
- The pull request description links both the feature issue and the design discussion.
- Every template instruction and placeholder is removed or filled in.
- Conditional sections that do not apply are omitted rather than left empty.
- Every requirement and acceptance criterion is covered by the design. Move anything deferred into a future specification.
- The threat model records no exploitable, unmitigated threat. Report those through a private security advisory instead, and keep only a bounded residual risk in the public file.
How the pull request is reviewed
Minor issues are resolved in the pull request. Unclear wording, a missing acceptance criterion, a threat that needs a stated mitigation, or a subsection in the wrong place are all review comments to address on the branch.
Major concerns send the design back a step. If review shows that the agreed approach does not hold, for example the architecture does not fit the problem, the scope is misjudged, or a trust boundary cannot be defended, the pull request is closed and the conversation returns to the design discussion. Open a new specification pull request once that discussion converges again.
After the specification is merged
Development starts once the specification is merged. Reference it from your implementation pull requests, and write your tests against the acceptance criteria in spec.md.
Both documents describe the feature as built, not only as planned. When implementation forces a design change, update them in the same pull request that changes the behavior, and add a row to the change log table in spec.md. If the change alters a trust boundary, an actor's entitlements, or an interaction, update threat-model.md alongside it.