Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,9 @@ for full ownership details.
### Architecture documentation

- ADRs go in `docs/architecture/adr/` with format `####-title.md`
- Follow existing ADR structure (Status, Context, Decision, Consequences)
- Follow the MADR structure from the template on the ADR index (`docs/architecture/adr/index.mdx`):
frontmatter (`adr`, `status`, `date`, `tags`), Context and problem statement, Considered options,
Decision outcome
Comment thread
withinfocus marked this conversation as resolved.

## Testing before committing

Expand Down
2 changes: 2 additions & 0 deletions custom-words.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ LLDB
Lucidchart
Mailcatcher
minio
mortems
MVVM
NGRX
Napi
Expand Down Expand Up @@ -107,6 +108,7 @@ typecheck
typechecks
typesafe
udeps
ungated
unsynchronized
WCAG
weweave
Expand Down
18 changes: 9 additions & 9 deletions docs/architecture/adr/0033-adopt-mermaid-diagram-standard.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ audience-specific views -- requires substantial rework per audience in practice.
## Decision outcome

Chosen option: **Mermaid with defined conventions**, published as the
[diagram standard](../../contributing/diagrams.md) on the contributing site. The standard is the
living reference and its rules evolve by PR without superseding this decision. This ADR is
superseded only if the chosen option itself changes. A snapshot of the rules at adoption:
[diagram standard](../../contributing/documentation/diagrams.md) on the contributing site. The
standard is the living reference and its rules evolve by PR without superseding this decision. This
ADR is superseded only if the chosen option itself changes. A snapshot of the rules at adoption:

1. Diagrams are Mermaid source text, nothing else: as Mermaid code blocks, or, if in Confluence, via
Macro Pack's Mermaid diagram in text-input mode.
Expand Down Expand Up @@ -80,12 +80,12 @@ superseded only if the chosen option itself changes. A snapshot of the rules at

### Plan

The standard is published at Contributing › Diagrams, and the bulk of the contributing site's
existing diagrams (PlantUML/Kroki sources, static diagram assets, and source-less images) have been
converted to comply, so the site becomes the reference implementation of the standard, with the
exceptions noted below. Elsewhere, legacy diagrams convert when their docs are next touched: images
and non-Mermaid sources in repos become Mermaid code blocks, and Confluence attachments and images
become Macro Pack's Mermaid diagram in text-input mode.
The standard is published at Contributing › Documentation › Diagrams, and the bulk of the
contributing site's existing diagrams (PlantUML/Kroki sources, static diagram assets, and
source-less images) have been converted to comply, so the site becomes the reference implementation
of the standard, with the exceptions noted below. Elsewhere, legacy diagrams convert when their docs
are next touched: images and non-Mermaid sources in repos become Mermaid code blocks, and Confluence
attachments and images become Macro Pack's Mermaid diagram in text-input mode.

The remaining adoption work is delegated to its owners:

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
---
Comment thread
MGibson1 marked this conversation as resolved.
adr: "0034"
status: Accepted
date: 2026-08-05
tags: [clients, mobile, server, sdk]
---

# 0034 - Adopt engineering documentation standard

<AdrTable frontMatter={frontMatter}></AdrTable>

## Context and problem statement

Documentation practice has fragmented as the organization has grown:

- Major repos use divergent layouts (`docs/`, `Docs/`, per-crate READMEs, none), inconsistent README
casing and quality, and no shared definition of what must be documented where.
- The de facto standards page lives in Confluence and is not enforced; practice diverges from it.
- Content sits in the wrong home: single-repo architecture on this site, shipped-code architecture
deep dives in Confluence, production runbooks in personal spaces, and duplicated guidance across
homes.
- Stale content accumulates with no supersession discipline, leaving superseded pages beside current
ones with no deprecation.
- AI agents have become first-class documentation consumers and maintainers, and their instruction
files (`CLAUDE.md`, rules, and skills across all repos) accumulate documentation-like content with
nothing defining whether they are documentation at all.

A 2026-07 audit classified every documentation artifact across the major repos, this site, and
Confluence against a proposed routing model, confirming these gaps.

## Considered options

- **Status quo:** per-team conventions, advisory Confluence page.
- **Confluence-first:** centralize engineering docs in the wiki.
- **Per-repo standards:** each repo defines its own documentation rules and keeps its own ADRs.
- **One org-wide, docs-as-code documentation standard:** close-to-code default, single routing
model, enforced through PR review and AI-agent guardrails.

## Decision outcome

Chosen option: **one org-wide, docs-as-code documentation standard**, published as the
[Documentation section](../../contributing/documentation/index.md). The standard is the living
reference. Its rules evolve by PR without superseding this decision and this ADR is superseded only
if the model itself changes. A snapshot of the rules at adoption:

1. **Public by default**. Private content is limited to documentation about working at Bitwarden and
sensitive information.
2. **Located at the lowest common ancestor** of what is described.
3. **Every doc has an audience**. AI agents and humans are both first-class audiences and
maintainers.
4. **Always up to date**. Doc maintenance is a top priority and happens alongside changes to what it
describes.
5. **Discoverable and unified**, enforced by the style guide the standard publishes.

Diagrams follow the separate diagram standard adopted in
[ADR-0033](./0033-adopt-mermaid-diagram-standard.md), which keeps its own living reference at
Contributing › Documentation › Diagrams.

AI instruction files are explicitly not documentation and are out of the standard's scope. Their
guidance lives with the AI tooling.

### Positive consequences

- One place to answer "where does this doc live" and "which docs do I update", for engineers and AI
agents alike.
- Documentation rides the code PR, so freshness is enforced by review and agent guardrails.
- Public-by-default locations serve external contributors and AI agents without special access.

### Negative consequences

- A migration backlog: existing content sits in homes the routing model forbids and must move.
- Strict-move deletions can break unknown inbound links. Known links are updated at move time and
link checkers in CI are the mitigation for the rest.
- Every repo carries adoption work before the standard applies in practice.

### Plan

Follow-up PRs complete the standard:

- The standard, with its format guidance and templates, publishes as the Documentation section under
Contributing and becomes the living reference this ADR mandates.
- The doc-currency plugin, which enforces rule 4, publishes in
[bitwarden/ai-plugins](https://github.com/bitwarden/ai-plugins) and distributes the root
`CLAUDE.md` documentation obligations.
- Each repo adopts the standard: base documentation obligations in the root `CLAUDE.md`, a
`CONTRIBUTING` pointer, and markdown tooling parity.
- Remediation work items are filed for every rule that current reality violates, and the superseded
Confluence standards page is deleted.

The migration backlog proceeds opportunistically under named owners. Small one-shot fixes are
tracked as work items; the long-running efforts:

- **Single-repo content migrates off this site**: `architecture/{clients,server,sdk,mobile-clients}`
and 12 of 28 deep-dive pages (including the whole `autofill/` subtree) move into their repos per
the routing table. Contributing docs' Deep Dives section holds only cross-repo or conceptual
material.
- **Shipped-code architecture migrates out of Confluence**: pages describing shipped code (the SSH
agent suite, event collection, key management cryptography) move in-repo or to this site per the
decision rule.
- **README coverage in Bitwarden repositories**: generated stubs and missing module READMEs brought
to the module README standard, and filename casing normalized.
- **Confluence hygiene**: stale and superseded pages deleted or stale-marked, and team runbook
indexes adopt the runbook standard and its Last verified discipline.
- **Incident documentation consolidation**: RCAs converge on the incident.io export as the single
home.
- **Style long tail**: style violations fixed across the site as pages are touched.
62 changes: 62 additions & 0 deletions docs/architecture/adr/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,68 @@ the thinking process and alternatives considered rather than simply stating what
if an ADR doesn't cover every edge case or alternative it provides valuable context and can be
refined through discussion.

## Format

ADRs follow the [MADR](https://adr.github.io/madr/) structure: a context and problem statement, the
considered options, and the decision outcome with its consequences. Start from the template below.

Each ADR is a file named `NNNN-short-title.md` in `docs/architecture/adr/`, numbered with the next
unused number. Refer to an ADR elsewhere by that number as ADR-NNNN, linking the file relatively so
the reference survives a move of this section.

<details>
<summary>ADR template</summary>

Delete the guidance comments before opening the pull request.

```text
---
adr: "NNNN"
status: Proposed
date: YYYY-MM-DD
tags: [clients, mobile, server, sdk]
---

# NNNN - Short imperative title

<AdrTable frontMatter={frontMatter}></AdrTable>

{/* Optional "## Notation" section here if the ADR relies on notation (RFC 2119
keywords, symbols). Delete when unused. */}

## Context and problem statement

{/* 2–4 paragraphs. What situation forces a decision? What breaks or
stays painful if we decide nothing? Link code, issues, and prior ADRs. */}

## Considered options

- **Option A:** one-line description.
- **Option B:** one-line description.

{/* Optional per-option subsections with pros/cons when the tradeoffs
need more than a line. Include "do nothing" when it is a real option. */}

## Decision outcome

Chosen option: **Option A**, because {decisive reason}.

### Positive consequences

- ...

### Negative consequences

- ...

### Plan

{/* How the decision takes effect: the follow-up work, migrations, and owners.
Delete when the ADR needs no follow-up. */}
```

</details>

## Status definition

ADRs progress through different statuses throughout their lifecycle. Understanding these statuses
Expand Down
62 changes: 62 additions & 0 deletions docs/contributing/documentation/component-documentation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
sidebar_position: 1
---

# Component documentation

**Audience:** Bitwarden engineers and AI agents writing or consuming in-repo documentation.

Notation follows the [documentation standard's Notation](./index.md#notation). These requirements
hold for every repo for as long as it lives, enforced by review and the doc-currency plugin. New
repositories satisfy them at initialization by starting from
[bitwarden/template](https://github.com/bitwarden/template). Existing repos converge per
[Changes to this standard](./index.md#changes-to-this-standard). Additional local guidance MAY be
layered on top, as each situation dictates.

Any component that other engineers or agents consume (that is, it exposes a public interface) MUST
have an **entry point for its scope's documentation**, at every scope from a single component to the
repo root. The entry point lives where the component's ecosystem surfaces documentation:

- At **component scope**, the entry point is the `README.md`, which registries render for packaged
components (a crate, an npm package, a NuGet project). Rust crates keep the README and the rustdoc
landing page one artifact with `#![doc = include_str!("../README.md")]`.
- **Below component scope**, the entry point is the language's module-level documentation where it
exists (`//!` in Rust), since a README there duplicates what the toolchain already owns and no
tooling surfaces it. It SHOULD be lint-enforced where the language supports it (Rust's
`missing_docs`).
- At **container and system scopes** (a container grouping several components, the repo root), the
entry point is a `README.md`, since no language ecosystem claims them.

Whatever its carrier, the entry point MUST contain:

1. **Purpose:** what problem this component solves, in 1–3 sentences.
2. **Key concepts:** the domain model or invariants a consumer must know (e.g., `libs/state`'s
data-loss warning on key renames; `bitwarden-crypto`'s `derive_`/`make_` naming rules).
3. **Usage:** the primary entry points, with a short code sample where the API is not self-evident.
4. **Gotchas / constraints:** the things that bite people (e.g., `libs/auth`'s "do not add new code
here" notice). This section MUST exist when such constraints do and MUST NOT exist when they do
not.

Documentation grows outward from the entry point of the
[lowest common ancestor](./index.md#where-documentation-lives-rules-1-2) of the code it describes. A
guide spanning several components therefore belongs to their parent scope:

1. Everything starts at the scope's entry point.
2. A single topic that deserves its own document becomes a named `.md` next to the code it
describes, linked from the entry point (`apps/browser/src/autofill/lifecycle.design.md` is the
exemplar).
3. When the scope's documentation outgrows this, it splits into a `docs/` folder (exactly that name,
lowercase) at the scope root. `docs/` exists only beside the entry point it extends: at the repo
root (`clients/docs/cipher-types.md` is the exemplar) or a component with its own entry point
(`util/Seeder/Seeds/docs/`), never an arbitrary subdirectory.

Scopes layer and multiple perspectives exist. A parent scope's documentation MAY describe the same
code at a higher altitude, sanding off detail the deeper docs own and linking down to them, and the
same subject MAY be documented separately per audience. Both are approved. Duplication is two
artifacts sharing one perspective.

Below component scope, reference documentation is code: doc comments on public symbols, reviewed and
merged with functionality, lint-enforced where the platform supports it. Doc comments MUST follow
the language's documentation norms for structure and detail. Where not enforced by the type system,
doc comments MUST say what a caller needs (behavior, invariants, error cases). Repos with doc CI
SHOULD fail the build on broken docs (the `sdk-internal` `cargo doc -D warnings` pattern).
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
sidebar_position: 2
sidebar_position: 5
---

# Diagram standard
Expand Down Expand Up @@ -105,7 +105,7 @@ C4 is adopted as a **mental model only**. We are explicitly **NOT** adopting any

## Ownership and currency (rules 7 and 8)

- The owner is CODEOWNERS for in-repo docs and the page's owning team on Confluence.
- The owner is `CODEOWNERS` for in-repo docs and the page's owning team on Confluence.
- Updates land in the same PR or page edit as the change the diagram depicts. A diagram known to be
wrong is deleted or updated rather than left to mislead.
- Every repo's root `CLAUDE.md` MUST carry the base documentation obligations, which cover diagrams:
Expand Down
Loading