From 96455d80d56a119eb79d34460c9421374cc4f0fe Mon Sep 17 00:00:00 2001 From: romchornyi Date: Tue, 3 Nov 2026 23:38:38 +0200 Subject: [PATCH 1/8] docs: add the decision log, the docs folder guide and the ADR rule Establish docs/ as the home for decisions and architecture docs: - docs/adr/: the decision log index, ADR-0001 (the ADR rules) and ADR-0002 (where the log lives), both Proposed until approved. - docs/README.md: what is required, what is optional, the layout and the publicity rule. - docs/architecture/README.md: the architecture section stub. - docs/features/docs-and-adr-layout/README.md: the feature summary. - PR template: the ADR item and the publicity item. - CLAUDE.md: the Architecture decisions and Publicity rules for agents. Co-Authored-By: Claude Opus 5.5 SDD-Published-From: 2e01f9270d417f5f66579915471cac3b24c655b8 --- .github/PULL_REQUEST_TEMPLATE.md | 2 + CLAUDE.md | 11 ++ docs/README.md | 52 ++++++++ ...1-record-architecture-decisions-as-adrs.md | 121 ++++++++++++++++++ .../0002-keep-the-decision-log-in-docs-adr.md | 51 ++++++++ docs/adr/README.md | 36 ++++++ docs/architecture/README.md | 6 + docs/features/docs-and-adr-layout/README.md | 40 ++++++ 8 files changed, 319 insertions(+) create mode 100644 docs/README.md create mode 100644 docs/adr/0001-record-architecture-decisions-as-adrs.md create mode 100644 docs/adr/0002-keep-the-decision-log-in-docs-adr.md create mode 100644 docs/adr/README.md create mode 100644 docs/architecture/README.md create mode 100644 docs/features/docs-and-adr-layout/README.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 5750fdbd98..362f6592c7 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -27,6 +27,8 @@ - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation +- [ ] ADR ([ADR-0001](https://github.com/dashpay/dashwallet-ios/blob/develop/docs/adr/0001-record-architecture-decisions-as-adrs.md)), keep the answer that applies: `ADR-NNNN added` · `no significant decision` · `not needed: ` +- [ ] Nothing in this PR (files, commit messages, description, comments, attachments) holds customer data, unfixed vulnerability detail, secrets, or step-by-step attack detail against keys, PIN or encryption; such content is left out and handled privately with the maintainers ([ADR-0001, rule 2](https://github.com/dashpay/dashwallet-ios/blob/develop/docs/adr/0001-record-architecture-decisions-as-adrs.md)) **For repository code-owners and collaborators only** - [ ] I have assigned this pull request to a milestone \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md index b00dabdc6d..e39b781eef 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -114,6 +114,17 @@ Distilled from the 2026-07 branch review (`ARCH_REVIEW_2026-07-03.md`) — each 6. **No debug residue in commits:** no session tags in log lines (à la `CJTEST`), no plan-diary comments ("Row #17 stage A", "M5/M6"), no stale line-number cross-references in doc comments. Use `TODO(label)` and link docs instead. 7. **Legacy compatibility stays bounded and honest.** Do not restore staged DashSync/SDK paths. Only the frozen key migrator may read the old `org.dashfoundation.dash` keychain layout. A seam method's name must match its behavior (`prepare` must not spend; `broadcast` must broadcast). +## Architecture decisions + +- Before changing an area, read the Accepted ADRs for it in the decision log, [`docs/adr/README.md`](docs/adr/README.md). +- Never silently contradict an Accepted ADR: name it and propose superseding it with a new ADR. +- An ADR you draft stays Proposed until a human Reviewer who is not its author approves the PR; your own approval never counts. After that approval, setting Accepted is a status-only change (ADR-0001 rule 3). +- Record a significant decision as an ADR in the same PR that makes it (threshold and "not needed" cases: ADR-0001). + +## Publicity + +The repository is public. Never put customer data, unfixed vulnerability detail, secrets or step-by-step attack detail against keys, PIN or encryption into files, commit messages, PRs, issues or their attachments; describe a support case by its symptom (ADR-0001 rule 2). + ## Code Style - **Swift**: SwiftFormat / SwiftLint (configs in `.swiftformat`, `.swiftlint.yml`). Avoid wholesale `@objcMembers` exposure (enforced by a custom SwiftLint rule). diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000000..e53b545528 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,52 @@ +# docs + +If this page and [ADR-0001](adr/0001-record-architecture-decisions-as-adrs.md) disagree, ADR-0001 wins. + +This folder holds the written record of dashwallet-ios: decisions, architecture docs, feature +folders and review captures. The repository is public, so everything here is public from the +first push of its branch. + +## Required + +ADRs for significant decisions are required for everyone, whether or not you use the feature-spec +pipeline. An ADR (architecture decision record) is a short document that states one decision, why +it was made, the options considered and its consequences. + +A decision is significant when it is hard to reverse, or affects more than one module or consumer. +The full rule, its examples and the "not needed" cases N1–N4 are in +[ADR-0001](adr/0001-record-architecture-decisions-as-adrs.md). The decision log and how to +add an ADR to it are in [adr/README.md](adr/README.md). + +## Optional + +Feature summaries are optional. A feature built with the feature-spec pipeline gets one file, +`docs/features//README.md`: what changed, why, and links to its ADRs. The pipeline's working +drafts (spec, design, tasks, reviews) are not committed. Its ADRs are copied into `docs/adr/` in the +feature PR and follow the same rules as any other ADR. + +## Layout + +| Path | Holds | Lifecycle | +|---|---|---| +| `docs/README.md` | this guide | edited as the layout changes | +| `docs/adr/` | the decision log: `NNNN-*.md` files and the index `README.md` | new entries; an existing ADR changes only its status line (ADR-0001 rule 3) | +| `docs/architecture/` | architecture docs | living, edited as the code changes | +| `docs/features//README.md` | one summary per feature | written in the feature PR | +| `docs/review/` | review captures | unchanged | + +## Publicity rule + +The repository is public: everything here, and everything else committed, pushed or posted on its +PRs and issues, is public too. Never write, here or anywhere in the repository and its PRs: + +- customer data, including anything taken from a support case; +- details of a vulnerability that is not fixed yet; +- secrets: keys, tokens, credentials, recovery phrases; +- step-by-step attack detail against keys, PIN or encryption. + +Describing the security design at the level already public in the code is allowed. Leave content +the rule keeps out of the repository and handle it privately with the maintainers; a doc may say +only that the detail is handled privately. A support case is described by its symptom, never by +the customer. Keep it out before pushing: the PR template's publicity +item, checked by the Reviewer, is the last net, not the first. Full rule: +[ADR-0001, rule 2](adr/0001-record-architecture-decisions-as-adrs.md). diff --git a/docs/adr/0001-record-architecture-decisions-as-adrs.md b/docs/adr/0001-record-architecture-decisions-as-adrs.md new file mode 100644 index 0000000000..7a99624167 --- /dev/null +++ b/docs/adr/0001-record-architecture-decisions-as-adrs.md @@ -0,0 +1,121 @@ +# 0001 — Record architecture decisions as ADRs + +- **Status:** Proposed +- **Date:** 2026-11-03 +- **Deciders:** romchornyi (author). Team agreement comes through the review of #1308 by llbartekll and jeanpierreroma. + +## Context + +dashwallet-ios has no agreed place for decisions. Decisions are not recorded in a form that says what was decided, why, and what later replaced it. Developers re-argue settled choices, Reviewers judge changes without the reasoning, and AI agents read only the agent instructions file (`CLAUDE.md`). The team is also starting to use a feature-spec pipeline that writes feature ADRs under its own per-feature numbering. Its working drafts are not committed; a feature publishes a short summary and its ADRs. The repository is public, so every document is published the moment its branch is pushed. + +## Decision drivers + +- Every significant decision has one findable record with its reasoning and current status, in one place and under one numbering. +- The rule is shared: the whole team agrees to it and writes ADRs, not only the owner. +- Nothing published through the repository exposes customer data or exploitable security detail; 0 publicity-rule breaches reach the default branch. +- 100% of log ADRs are listed in the index with the correct status. +- Every primary source checked keeps one central, sequentially numbered log and states the threshold as a principle with exclusions, never as a pure category list (fact-check 2026-11-03: Nygard, MADR, Polar handbook). + +## Considered options + +1. **One central, sequentially numbered decision log with a rule that binds every Developer** — the rules below. +2. **ADRs kept by the owner alone, with no team rule** — less discipline asked of others, but the records cover only one person's work. +3. **ADRs only inside feature folders, under the pipeline's per-feature numbering, with no central log** — no extra step, but decisions are scattered under many numberings, and Developers who do not use the pipeline have nowhere to write. +4. **One central log as in option 1, but only feature ADRs above the significance threshold are promoted** — the log grows more slowly, but every feature PR needs a per-ADR judgement about which drafts to promote, and unpromoted drafts stay in feature folders as a second set of numbered decisions. + +## Decision outcome + +**Chosen:** option 1, with every feature ADR that the feature keeps promoted. It is the only option that meets the first two drivers together: one place and one numbering, shared by everyone. Over option 4 the owner chose one simple rule (promote everything) and accepted a faster-growing log; the threshold therefore governs decisions made outside the pipeline. The rules below also carry the publicity driver, which neither option 2 nor option 3 addresses. + +### Rule 1 — Significance threshold + +A decision needs an ADR when it is **hard to reverse, or affects more than one module or consumer**. + +Examples in this wallet: + +- a new dependency or SDK; +- a storage schema or migration; +- the key and security model; +- a module boundary; +- a contract with platform or rust-dashcore. + +**Not needed** — a code comment or the PR description covers these: + +- **N1** — a local, easily reversible choice inside one module (naming, internal structure, a private helper); +- **N2** — a temporary workaround, marked `TODO(label)` in the code; +- **N3** — a bug fix that restores the intended behaviour without changing a contract; +- **N4** — a change that follows an Accepted ADR without changing its decision. + +The PR template's ADR item is answered with one of: `ADR-NNNN added`, `no significant decision`, or `not needed: `. + +### Rule 2 — Publicity + +The repository is public. Everything that goes through it is public the moment it is pushed or posted: + +- every committed file, anywhere in the tree: code and its comments, tests and fixtures, `docs/`, `CLAUDE.md`, the root documentation files, configuration; +- commit messages and branch names; +- the titles, descriptions and comments of PRs and issues, review comments and replies, and the files attached to them (screenshots, logs, crash reports). + +Never put there: + +- customer data, including anything taken from a support case; +- details of a vulnerability that is not fixed yet; +- secrets: keys, tokens, credentials, recovery phrases; +- step-by-step attack detail against keys, PIN or encryption. + +Describing the security design at the level already public in the code is allowed. Content that the rule keeps out is left out of the repository and handled privately with the maintainers; a document, comment or PR may say only that the detail is handled privately. A support case is described by its symptom, never by the customer: no names, emails, addresses, transaction ids, wallet ids or unredacted logs and screenshots. + +The author keeps such content out **before pushing**. The PR template's publicity item, checked by the Reviewer, is the last net and not the first. When a breach is found: + +- in a file: it is removed and a short note says that the file was redacted and why. This redaction is allowed even in an Accepted ADR: the publicity rule wins over rule 3's "never edited". Git history still holds the removed text; +- in PR or issue text or an attachment: the comment or file is deleted, and an edited description also has the old revision deleted from its edit history, which GitHub otherwise shows to everyone. + +A secret that reached any pushed branch or any PR text is treated as leaked and rotated, even if it was removed before merge. + +### Rule 3 — Lifecycle, numbering and supersede + +- A new ADR takes the next free log number, starts as **Proposed**, and is listed in the index (`docs/adr/README.md`) in the same PR. +- An ADR becomes **Accepted** only when a Reviewer who is not its author approves the PR that carries it. An AI agent's approval never counts. After the approval, the author sets Accepted in the ADR and in the index as the last change before merge; this status-only change needs no new approval. +- The Status line is the ADR's only status field. An ADR in `docs/adr/` has no frontmatter. +- An Accepted ADR is **never edited**. The only exceptions are its status line when it is superseded and a redaction that rule 2 requires. +- To change a decision, write a new ADR that names the old one. In the old ADR only the status line changes, to `Superseded by ADR-NNNN`. +- A number is **never reused**. If two open PRs take the same number, the author of the PR that merges second moves the ADR to the next free number when rebasing and updates every reference to the old number in that PR. A renumbering alone needs no new approval. Before merging, the author checks that the number is still free on `develop`. + +### Rule 4 — Promotion of feature ADRs + +Every feature ADR that the feature keeps goes to the decision log in the feature PR itself. A draft the pipeline rejected or replaced is not copied. + +- it is copied to `docs/adr/` under the next free log number, without the pipeline's frontmatter, with the status Proposed, and listed in the index; from then on the copy in `docs/adr/` is the record; +- it becomes Accepted under rule 3, like any other ADR; +- the feature's public summary, `docs/features//README.md`, links it by its log number; +- the index lists log numbers only. + +The status that the pipeline wrote into a draft does not count. + +### Rule 5 — Shape, and who writes ADRs + +- File: `docs/adr/NNNN-.md`. The title states the decision, not the problem. +- Body: the Status, Date and Deciders lines, then Context, Decision drivers, Considered options, Decision outcome, Consequences and Links. Considered options and Consequences are required. Feature ADRs use the same shape, so promotion is a copy, not a rewrite. Links are relative to the file (`../README.md`), so they work on GitHub and in a local checkout, and point only at what is in the repository. +- Every Developer writes ADRs for their significant decisions, whether or not they use the feature-spec pipeline. Feature summaries are optional. +- Past decisions get an ADR when they are next revisited; no retroactive backlog is required. + +## Consequences + +**Positive** +- Each significant decision has one record with its reasoning and its current status, findable from one index. +- Reviewers have a checklist item for asking for a missing ADR, and a written "not needed" list for accepting its absence. +- AI agents get a named source of settled decisions and a way to challenge one (supersede) instead of silently contradicting it. +- The publicity rule is written down and checked on every PR, for its files, its commits and its text. + +**Negative** +- Every significant PR carries an extra document, and every PR carries two more checklist items. +- The log grows faster than a log that holds only threshold-level decisions, because every feature ADR that a feature keeps is promoted, including the small ones the pipeline produces by quota. +- Little is automated: the repository's gitleaks pre-commit hook (`.githooks/`, enabled per clone) catches secrets; index completeness, numbering and the other publicity cases rely on the Reviewer. + +**Neutral** +- If the co-maintainers do not agree to a mandatory rule, this ADR is changed in its own PR before approval: the ADR checklist item becomes optional and ADRs are written by those who choose to. The publicity item stays mandatory, because the repository is public whatever the team decides. + +## Links + +- Feature summary: [docs/features/docs-and-adr-layout/README.md](../features/docs-and-adr-layout/README.md) +- Related ADR: [0002 — Keep the decision log in docs/adr](0002-keep-the-decision-log-in-docs-adr.md) diff --git a/docs/adr/0002-keep-the-decision-log-in-docs-adr.md b/docs/adr/0002-keep-the-decision-log-in-docs-adr.md new file mode 100644 index 0000000000..930b58d2fe --- /dev/null +++ b/docs/adr/0002-keep-the-decision-log-in-docs-adr.md @@ -0,0 +1,51 @@ +# 0002 — Keep the decision log in docs/adr + +- **Status:** Proposed +- **Date:** 2026-11-03 +- **Deciders:** romchornyi (author) + +## Context + +The decision log needs a fixed path. `CLAUDE.md`, the PR template, the docs folder guide, the feature-spec pipeline's promotion step, and links from issues and PRs all refer to it. On `develop`, `docs/` holds only `docs/review/`. The rest of the docs folder layout is decided together with the log's home, because the guide explains all the sections in one place. + +## Decision drivers + +- One place for every ADR, named so that people, agents and links can find it. +- Links from issues and PRs are permanent, so the path should not change once ADRs are linked. +- The pipeline already writes feature ADRs to an `adr/` folder, and promotion copies them into the log (ADR-0001 rule 4). + +## Considered options + +1. **`docs/adr/`** — the name used by Nygard's original post and adr-tools, and the same name as the pipeline's feature-folder subfolder. +2. **`docs/decisions/`** — the folder MADR recommends since version 3; it avoids the acronym and matches the glossary term "decision log". + +## Decision outcome + +**Chosen:** option 1, `docs/adr/`. It matches the pipeline's own `adr/` folder that promotion copies from. Option 2's main advantage, avoiding the acronym, is covered by the docs folder guide, which explains what an ADR is. + +The resulting layout of the docs folder: + +| Path | Holds | Lifecycle | +|---|---|---| +| `docs/README.md` | the docs folder guide: what is required (ADRs for significant decisions, for everyone), what is optional (feature summaries), where architecture docs and reviews go, and the publicity rule in short | edited as the layout changes | +| `docs/adr/` | the decision log: `NNNN-*.md` files and the index `README.md` (`# \| Title \| Status \| Superseded by`) | new entries; an existing ADR changes only its status line (ADR-0001 rule 3) | +| `docs/architecture/` | architecture docs | living, edited as the code changes | +| `docs/features//README.md` | one summary per feature: what changed, why, and links to its ADRs; the pipeline's working drafts are not committed | written in the feature PR | +| `docs/review/` | review captures (already exists) | unchanged | + +## Consequences + +**Positive** +- Promotion is a copy between two folders with the same name: `adr/` → `docs/adr/`. + +**Negative** +- "adr" is jargon; a newcomer learns its meaning from `docs/README.md`, not from the path. + +**Neutral** +- Renaming the folder later is a quick change inside the repository, but it breaks external links to ADRs. That is why this ADR exists. +- The loose root documentation files are not part of this layout until the follow-up PR moves them. + +## Links + +- Feature summary: [docs/features/docs-and-adr-layout/README.md](../features/docs-and-adr-layout/README.md) +- Related ADR: [0001 — Record architecture decisions as ADRs](0001-record-architecture-decisions-as-adrs.md) diff --git a/docs/adr/README.md b/docs/adr/README.md new file mode 100644 index 0000000000..1f965d48f0 --- /dev/null +++ b/docs/adr/README.md @@ -0,0 +1,36 @@ +# Decision log + +The architecture decision records (ADRs) of dashwallet-ios, governed by +[ADR-0001](0001-record-architecture-decisions-as-adrs.md). This index lists log numbers +only and is kept by hand. The notes below summarize ADR-0001; where they disagree, ADR-0001 wins. + +| # | Title | Status | Superseded by | +|---|---|---|---| +| [0001](0001-record-architecture-decisions-as-adrs.md) | Record architecture decisions as ADRs | Proposed | | +| [0002](0002-keep-the-decision-log-in-docs-adr.md) | Keep the decision log in docs/adr | Proposed | | + +## Adding an ADR + +- Take the next free number and name the file `NNNN-.md`; the title states + the decision, not the problem. +- Start it as Proposed. It becomes Accepted only after a Reviewer who is not its author approves + the PR that carries it. +- Follow the shape of ADR-0001: Status, Date and Deciders lines, then Context, Decision drivers, + Considered options, Decision outcome, Consequences and Links. Considered options and + Consequences are required. +- Add its row to the table above in the same PR. + +Full rules: [ADR-0001, rules 3 and 5](0001-record-architecture-decisions-as-adrs.md). + +## Superseding + +An Accepted ADR is never edited. To change a decision, write a new ADR that names the old one. In +the old ADR only the status line changes, to `Superseded by ADR-NNNN`; in its row here, Status reads +`Superseded` and "Superseded by" links the new ADR. See +[ADR-0001, rule 3](0001-record-architecture-decisions-as-adrs.md). + +## Number collisions + +A number is never reused. If two open PRs take the same number, the author of the PR that merges +second renumbers its ADR to the next free number when rebasing and updates every reference to the +old number in that PR. See [ADR-0001, rule 3](0001-record-architecture-decisions-as-adrs.md). diff --git a/docs/architecture/README.md b/docs/architecture/README.md new file mode 100644 index 0000000000..31a2113285 --- /dev/null +++ b/docs/architecture/README.md @@ -0,0 +1,6 @@ +# Architecture + +This section holds living architecture docs of dashwallet-ios. They are edited as the code changes. + +The architecture documents in the repository root are not moved yet; a follow-up change moves +them here. Decisions are recorded in the [decision log](../adr/README.md), not here. diff --git a/docs/features/docs-and-adr-layout/README.md b/docs/features/docs-and-adr-layout/README.md new file mode 100644 index 0000000000..aab30ee174 --- /dev/null +++ b/docs/features/docs-and-adr-layout/README.md @@ -0,0 +1,40 @@ +# Docs folder layout and the decision log + +**Status:** in review ([#1308](https://github.com/dashpay/dashwallet-ios/pull/1308)) · **Owner:** romchornyi + +## Why + +dashwallet-ios had no agreed place for its decisions. Nothing recorded what was decided, why, and +what later replaced it, so settled choices were re-argued and reviews ran without the reasoning. +The repository is public, so whatever is written under `docs/` is published from the first push. + +## What changed + +- **Decision log** in [`docs/adr/`](../../adr/README.md): one sequentially numbered log with an + index. ADRs for significant decisions are required for everyone. +- **The rules** are in [ADR-0001](../../adr/0001-record-architecture-decisions-as-adrs.md): the + significance threshold and its "not needed" cases, the publicity rule, the lifecycle + (Proposed → Accepted → Superseded, numbers never reused) and the promotion of feature ADRs. +- **The location** of the log is [ADR-0002](../../adr/0002-keep-the-decision-log-in-docs-adr.md). +- **Docs folder guide**, [`docs/README.md`](../../README.md): what is required, what is optional, + the layout, and the publicity rule in short. [`docs/architecture/`](../../architecture/README.md) + is the home for living architecture docs. +- **PR template**: an ADR item and a publicity item. +- **`CLAUDE.md`**: AI agents read the Accepted ADRs, never silently contradict one, and the ADRs + they draft stay Proposed. + +## What it guarantees + +- A significant decision gets an ADR in the same PR, with the next log number, status Proposed, + its alternatives and consequences, and a row in the index. +- An ADR becomes Accepted only after a Reviewer who is not its author approves the PR. +- An Accepted ADR is never edited; a new ADR supersedes it. +- Nothing in the repository or on its PRs holds customer data, unfixed vulnerability detail, secrets or + step-by-step attack detail against keys, PIN or encryption. + +## Not in scope + +- Moving the loose documentation files from the repository root into `docs/` is a follow-up PR. +- ADRs for past decisions are not written retroactively; a past decision gets one when it is next + revisited. +- Nothing is enforced automatically; the PR template and review carry the rule. From e2b70aceeaf3a6e1a134bd01462c1149294e2eee Mon Sep 17 00:00:00 2001 From: romchornyi Date: Wed, 4 Nov 2026 00:32:34 +0200 Subject: [PATCH 2/8] docs: name branch names and linked issues in the publicity checkbox, scope the enforcement note Closes the CodeRabbit review of 96455d80d: - PR template: the publicity checkbox now names the branch name and linked issues, matching ADR-0001 rule 2 - docs-and-adr-layout README: the enforcement note names the opt-in gitleaks pre-commit hook Co-Authored-By: Claude Opus 5.5 SDD-Published-From: 8c6b6a992dcfcb4272d1a9594e9408f88b2c9837 --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- docs/features/docs-and-adr-layout/README.md | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 362f6592c7..a1fbcf13df 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -28,7 +28,7 @@ - [ ] I have added or updated relevant unit/integration/functional/e2e tests - [ ] I have made corresponding changes to the documentation - [ ] ADR ([ADR-0001](https://github.com/dashpay/dashwallet-ios/blob/develop/docs/adr/0001-record-architecture-decisions-as-adrs.md)), keep the answer that applies: `ADR-NNNN added` · `no significant decision` · `not needed: ` -- [ ] Nothing in this PR (files, commit messages, description, comments, attachments) holds customer data, unfixed vulnerability detail, secrets, or step-by-step attack detail against keys, PIN or encryption; such content is left out and handled privately with the maintainers ([ADR-0001, rule 2](https://github.com/dashpay/dashwallet-ios/blob/develop/docs/adr/0001-record-architecture-decisions-as-adrs.md)) +- [ ] Nothing in this PR (files, commit messages, branch name, description, comments, attachments, linked issues) holds customer data, unfixed vulnerability detail, secrets, or step-by-step attack detail against keys, PIN or encryption; such content is left out and handled privately with the maintainers ([ADR-0001, rule 2](https://github.com/dashpay/dashwallet-ios/blob/develop/docs/adr/0001-record-architecture-decisions-as-adrs.md)) **For repository code-owners and collaborators only** - [ ] I have assigned this pull request to a milestone \ No newline at end of file diff --git a/docs/features/docs-and-adr-layout/README.md b/docs/features/docs-and-adr-layout/README.md index aab30ee174..5542bc11df 100644 --- a/docs/features/docs-and-adr-layout/README.md +++ b/docs/features/docs-and-adr-layout/README.md @@ -37,4 +37,5 @@ The repository is public, so whatever is written under `docs/` is published from - Moving the loose documentation files from the repository root into `docs/` is a follow-up PR. - ADRs for past decisions are not written retroactively; a past decision gets one when it is next revisited. -- Nothing is enforced automatically; the PR template and review carry the rule. +- Little is enforced automatically: the gitleaks pre-commit hook (`.githooks/`, enabled per clone) catches + secrets; the PR template and review carry the rest. From 83cfa96b35b7c0e7216ce23c7ef4642798f213ab Mon Sep 17 00:00:00 2001 From: romchornyi Date: Wed, 4 Nov 2026 01:03:59 +0200 Subject: [PATCH 3/8] docs: name branch names in the CLAUDE.md publicity rule Closes the thepastaclaw re-review of e2b70acee: - CLAUDE.md: the agent-facing publicity rule now names branch names, matching ADR-0001 rule 2 and the PR template Co-Authored-By: Claude Opus 5.5 SDD-Published-From: d96734b924b34b78fdee7060a7ea63a5f0d3f097 --- CLAUDE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index e39b781eef..035f877b82 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -123,7 +123,7 @@ Distilled from the 2026-07 branch review (`ARCH_REVIEW_2026-07-03.md`) — each ## Publicity -The repository is public. Never put customer data, unfixed vulnerability detail, secrets or step-by-step attack detail against keys, PIN or encryption into files, commit messages, PRs, issues or their attachments; describe a support case by its symptom (ADR-0001 rule 2). +The repository is public. Never put customer data, unfixed vulnerability detail, secrets or step-by-step attack detail against keys, PIN or encryption into files, commit messages, branch names, PRs, issues or their attachments; describe a support case by its symptom (ADR-0001 rule 2). ## Code Style From 4e0530015de38b24544edfa6632ce4e8f7c1836b Mon Sep 17 00:00:00 2001 From: romchornyi Date: Wed, 4 Nov 2026 01:32:37 +0200 Subject: [PATCH 4/8] docs: drop the transient review status from the docs-layout summary Closes the thepastaclaw re-review of 83cfa96b3: - docs-and-adr-layout README: the 'in review' status line is replaced by the owner and the PR that introduced it Co-Authored-By: Claude Opus 5.5 SDD-Published-From: 9551793df303d13fbb59018b7bb330f297f33d38 --- docs/features/docs-and-adr-layout/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/docs-and-adr-layout/README.md b/docs/features/docs-and-adr-layout/README.md index 5542bc11df..3f88938dfa 100644 --- a/docs/features/docs-and-adr-layout/README.md +++ b/docs/features/docs-and-adr-layout/README.md @@ -1,6 +1,6 @@ # Docs folder layout and the decision log -**Status:** in review ([#1308](https://github.com/dashpay/dashwallet-ios/pull/1308)) · **Owner:** romchornyi +**Owner:** romchornyi · Introduced in [#1308](https://github.com/dashpay/dashwallet-ios/pull/1308) ## Why From ace51c411d19a1733964eef6c5230a1cdc9ab27b Mon Sep 17 00:00:00 2001 From: romchornyi Date: Wed, 4 Nov 2026 12:10:03 +0200 Subject: [PATCH 5/8] docs: index ADRs by area and open Decision outcome with a Chosen sentence Closes the round-9 review of #1308: - the decision log index gains an Area column with a fixed list under it - CLAUDE.md reads the index first and opens only the ADRs whose Area matches - ADR-0001 rule 5 asks Decision outcome to open with one Chosen sentence Co-Authored-By: Claude Opus 5.5 SDD-Published-From: c41dcae9733a646aed1b732103bece3c6046a286 --- CLAUDE.md | 2 +- ...0001-record-architecture-decisions-as-adrs.md | 3 ++- .../0002-keep-the-decision-log-in-docs-adr.md | 2 +- docs/adr/README.md | 16 ++++++++++------ 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 035f877b82..0e53f202ae 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -116,7 +116,7 @@ Distilled from the 2026-07 branch review (`ARCH_REVIEW_2026-07-03.md`) — each ## Architecture decisions -- Before changing an area, read the Accepted ADRs for it in the decision log, [`docs/adr/README.md`](docs/adr/README.md). +- Before changing an area, read the index of the decision log, [`docs/adr/README.md`](docs/adr/README.md), and open only the Accepted ADRs whose Area matches the files you touch. - Never silently contradict an Accepted ADR: name it and propose superseding it with a new ADR. - An ADR you draft stays Proposed until a human Reviewer who is not its author approves the PR; your own approval never counts. After that approval, setting Accepted is a status-only change (ADR-0001 rule 3). - Record a significant decision as an ADR in the same PR that makes it (threshold and "not needed" cases: ADR-0001). diff --git a/docs/adr/0001-record-architecture-decisions-as-adrs.md b/docs/adr/0001-record-architecture-decisions-as-adrs.md index 7a99624167..9c81f6099a 100644 --- a/docs/adr/0001-record-architecture-decisions-as-adrs.md +++ b/docs/adr/0001-record-architecture-decisions-as-adrs.md @@ -95,7 +95,8 @@ The status that the pipeline wrote into a draft does not count. ### Rule 5 — Shape, and who writes ADRs - File: `docs/adr/NNNN-.md`. The title states the decision, not the problem. -- Body: the Status, Date and Deciders lines, then Context, Decision drivers, Considered options, Decision outcome, Consequences and Links. Considered options and Consequences are required. Feature ADRs use the same shape, so promotion is a copy, not a rewrite. Links are relative to the file (`../README.md`), so they work on GitHub and in a local checkout, and point only at what is in the repository. +- Body: the Status, Date and Deciders lines, then Context, Decision drivers, Considered options, Decision outcome, Consequences and Links. Considered options and Consequences are required. Decision outcome opens with one sentence, `**Chosen:** …`, that states the decision on its own. Feature ADRs use the same shape, so promotion is a copy, not a rewrite. Links are relative to the file (`../README.md`), so they work on GitHub and in a local checkout, and point only at what is in the repository. +- Index row: number, title, Area, Status and Superseded by. Area is one value from the fixed list under the index table; a new value is added to that list in the PR that first needs it. - Every Developer writes ADRs for their significant decisions, whether or not they use the feature-spec pipeline. Feature summaries are optional. - Past decisions get an ADR when they are next revisited; no retroactive backlog is required. diff --git a/docs/adr/0002-keep-the-decision-log-in-docs-adr.md b/docs/adr/0002-keep-the-decision-log-in-docs-adr.md index 930b58d2fe..816ab93934 100644 --- a/docs/adr/0002-keep-the-decision-log-in-docs-adr.md +++ b/docs/adr/0002-keep-the-decision-log-in-docs-adr.md @@ -28,7 +28,7 @@ The resulting layout of the docs folder: | Path | Holds | Lifecycle | |---|---|---| | `docs/README.md` | the docs folder guide: what is required (ADRs for significant decisions, for everyone), what is optional (feature summaries), where architecture docs and reviews go, and the publicity rule in short | edited as the layout changes | -| `docs/adr/` | the decision log: `NNNN-*.md` files and the index `README.md` (`# \| Title \| Status \| Superseded by`) | new entries; an existing ADR changes only its status line (ADR-0001 rule 3) | +| `docs/adr/` | the decision log: `NNNN-*.md` files and the index `README.md` (`# \| Title \| Area \| Status \| Superseded by`) | new entries; an existing ADR changes only its status line (ADR-0001 rule 3) | | `docs/architecture/` | architecture docs | living, edited as the code changes | | `docs/features//README.md` | one summary per feature: what changed, why, and links to its ADRs; the pipeline's working drafts are not committed | written in the feature PR | | `docs/review/` | review captures (already exists) | unchanged | diff --git a/docs/adr/README.md b/docs/adr/README.md index 1f965d48f0..b32ee77f8b 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -4,10 +4,13 @@ The architecture decision records (ADRs) of dashwallet-ios, governed by [ADR-0001](0001-record-architecture-decisions-as-adrs.md). This index lists log numbers only and is kept by hand. The notes below summarize ADR-0001; where they disagree, ADR-0001 wins. -| # | Title | Status | Superseded by | -|---|---|---|---| -| [0001](0001-record-architecture-decisions-as-adrs.md) | Record architecture decisions as ADRs | Proposed | | -| [0002](0002-keep-the-decision-log-in-docs-adr.md) | Keep the decision log in docs/adr | Proposed | | +| # | Title | Area | Status | Superseded by | +|---|---|---|---|---| +| [0001](0001-record-architecture-decisions-as-adrs.md) | Record architecture decisions as ADRs | process | Proposed | | +| [0002](0002-keep-the-decision-log-in-docs-adr.md) | Keep the decision log in docs/adr | process | Proposed | | + +Areas: `spv`, `platform`, `keys`, `storage`, `coinjoin`, `ui`, `build`, `process`. Each ADR takes one; a new +Area is added to this list in the PR that first needs it. ## Adding an ADR @@ -17,8 +20,9 @@ only and is kept by hand. The notes below summarize ADR-0001; where they disagre the PR that carries it. - Follow the shape of ADR-0001: Status, Date and Deciders lines, then Context, Decision drivers, Considered options, Decision outcome, Consequences and Links. Considered options and - Consequences are required. -- Add its row to the table above in the same PR. + Consequences are required. Decision outcome opens with one sentence, `**Chosen:** …`, that + states the decision on its own. +- Add its row to the table above in the same PR, with one Area from the list under it. Full rules: [ADR-0001, rules 3 and 5](0001-record-architecture-decisions-as-adrs.md). From ebff2c4bef69b74247ba753bab6df0e26d4fdd39 Mon Sep 17 00:00:00 2001 From: romchornyi Date: Wed, 4 Nov 2026 12:17:50 +0200 Subject: [PATCH 6/8] docs: name the approving reviewer in the ADR-0001 Deciders line Co-Authored-By: Claude Opus 5.5 SDD-Published-From: aa177dd8d1bd11a2c26d71f3db1f5d6b9b9199a7 --- docs/adr/0001-record-architecture-decisions-as-adrs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/adr/0001-record-architecture-decisions-as-adrs.md b/docs/adr/0001-record-architecture-decisions-as-adrs.md index 9c81f6099a..39e5379bdf 100644 --- a/docs/adr/0001-record-architecture-decisions-as-adrs.md +++ b/docs/adr/0001-record-architecture-decisions-as-adrs.md @@ -2,7 +2,7 @@ - **Status:** Proposed - **Date:** 2026-11-03 -- **Deciders:** romchornyi (author). Team agreement comes through the review of #1308 by llbartekll and jeanpierreroma. +- **Deciders:** romchornyi (author). Team agreement: approval of #1308 by llbartekll. ## Context From 6acde01b6ec817fc3f0da475b5a7663c6804d2c9 Mon Sep 17 00:00:00 2001 From: romchornyi Date: Wed, 4 Nov 2026 13:19:01 +0200 Subject: [PATCH 7/8] docs: name the publicity redaction exception in every ADR lifecycle summary Closes the round-10 review of #1308: - ADR-0002, docs/README.md, the index Superseding note and the docs-layout summary name the redaction that ADR-0001 rule 2 allows in an Accepted ADR - the index intro says it lists every log ADR under its log number, never a feature-local number Co-Authored-By: Claude Opus 5.5 SDD-Published-From: b4eed4c05f7f786ea5696a7bc35c0a38cc8a24dc --- docs/README.md | 2 +- docs/adr/0002-keep-the-decision-log-in-docs-adr.md | 2 +- docs/adr/README.md | 12 +++++++----- docs/features/docs-and-adr-layout/README.md | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/README.md b/docs/README.md index e53b545528..3cea9fdfa1 100644 --- a/docs/README.md +++ b/docs/README.md @@ -29,7 +29,7 @@ feature PR and follow the same rules as any other ADR. | Path | Holds | Lifecycle | |---|---|---| | `docs/README.md` | this guide | edited as the layout changes | -| `docs/adr/` | the decision log: `NNNN-*.md` files and the index `README.md` | new entries; an existing ADR changes only its status line (ADR-0001 rule 3) | +| `docs/adr/` | the decision log: `NNNN-*.md` files and the index `README.md` | new entries; an existing Accepted ADR changes only in its status line when superseded (ADR-0001 rule 3) or by a redaction that the publicity rule requires (ADR-0001 rule 2) | | `docs/architecture/` | architecture docs | living, edited as the code changes | | `docs/features//README.md` | one summary per feature | written in the feature PR | | `docs/review/` | review captures | unchanged | diff --git a/docs/adr/0002-keep-the-decision-log-in-docs-adr.md b/docs/adr/0002-keep-the-decision-log-in-docs-adr.md index 816ab93934..f5275ed8d3 100644 --- a/docs/adr/0002-keep-the-decision-log-in-docs-adr.md +++ b/docs/adr/0002-keep-the-decision-log-in-docs-adr.md @@ -28,7 +28,7 @@ The resulting layout of the docs folder: | Path | Holds | Lifecycle | |---|---|---| | `docs/README.md` | the docs folder guide: what is required (ADRs for significant decisions, for everyone), what is optional (feature summaries), where architecture docs and reviews go, and the publicity rule in short | edited as the layout changes | -| `docs/adr/` | the decision log: `NNNN-*.md` files and the index `README.md` (`# \| Title \| Area \| Status \| Superseded by`) | new entries; an existing ADR changes only its status line (ADR-0001 rule 3) | +| `docs/adr/` | the decision log: `NNNN-*.md` files and the index `README.md` (`# \| Title \| Area \| Status \| Superseded by`) | new entries; an existing Accepted ADR changes only in its status line when superseded (ADR-0001 rule 3) or by a redaction that the publicity rule requires (ADR-0001 rule 2) | | `docs/architecture/` | architecture docs | living, edited as the code changes | | `docs/features//README.md` | one summary per feature: what changed, why, and links to its ADRs; the pipeline's working drafts are not committed | written in the feature PR | | `docs/review/` | review captures (already exists) | unchanged | diff --git a/docs/adr/README.md b/docs/adr/README.md index b32ee77f8b..73ea18d239 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -1,8 +1,9 @@ # Decision log The architecture decision records (ADRs) of dashwallet-ios, governed by -[ADR-0001](0001-record-architecture-decisions-as-adrs.md). This index lists log numbers -only and is kept by hand. The notes below summarize ADR-0001; where they disagree, ADR-0001 wins. +[ADR-0001](0001-record-architecture-decisions-as-adrs.md). It lists every log ADR under its log +number, never a feature-local number, and is kept by hand. The notes below summarize ADR-0001; +where they disagree, ADR-0001 wins. | # | Title | Area | Status | Superseded by | |---|---|---|---|---| @@ -28,9 +29,10 @@ Full rules: [ADR-0001, rules 3 and 5](0001-record-architecture-decisions-as-adrs ## Superseding -An Accepted ADR is never edited. To change a decision, write a new ADR that names the old one. In -the old ADR only the status line changes, to `Superseded by ADR-NNNN`; in its row here, Status reads -`Superseded` and "Superseded by" links the new ADR. See +An Accepted ADR is never edited, except for a redaction that the publicity rule requires (ADR-0001 +rule 2). To change a decision, write a new ADR that names the old one. In the old ADR only the +status line changes, to `Superseded by ADR-NNNN`; in its row here, Status reads `Superseded` and +"Superseded by" links the new ADR. See [ADR-0001, rule 3](0001-record-architecture-decisions-as-adrs.md). ## Number collisions diff --git a/docs/features/docs-and-adr-layout/README.md b/docs/features/docs-and-adr-layout/README.md index 3f88938dfa..cde33bb7d0 100644 --- a/docs/features/docs-and-adr-layout/README.md +++ b/docs/features/docs-and-adr-layout/README.md @@ -28,7 +28,7 @@ The repository is public, so whatever is written under `docs/` is published from - A significant decision gets an ADR in the same PR, with the next log number, status Proposed, its alternatives and consequences, and a row in the index. - An ADR becomes Accepted only after a Reviewer who is not its author approves the PR. -- An Accepted ADR is never edited; a new ADR supersedes it. +- An Accepted ADR is never edited, except for a redaction that the publicity rule requires; a new ADR supersedes it. - Nothing in the repository or on its PRs holds customer data, unfixed vulnerability detail, secrets or step-by-step attack detail against keys, PIN or encryption. From 90285b888b0203da86e4742d6a5a1412e18fe1d9 Mon Sep 17 00:00:00 2001 From: romchornyi Date: Wed, 4 Nov 2026 13:24:00 +0200 Subject: [PATCH 8/8] docs: accept ADR-0001 and ADR-0002 Status-only change after the approval of #1308 by llbartekll (ADR-0001 rule 3). Co-Authored-By: Claude Opus 5.5 SDD-Published-From: 852b9106a0d0bfea44b70e6da0b2d35a1c489b44 --- docs/adr/0001-record-architecture-decisions-as-adrs.md | 2 +- docs/adr/0002-keep-the-decision-log-in-docs-adr.md | 2 +- docs/adr/README.md | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/adr/0001-record-architecture-decisions-as-adrs.md b/docs/adr/0001-record-architecture-decisions-as-adrs.md index 39e5379bdf..17980fc11d 100644 --- a/docs/adr/0001-record-architecture-decisions-as-adrs.md +++ b/docs/adr/0001-record-architecture-decisions-as-adrs.md @@ -1,6 +1,6 @@ # 0001 — Record architecture decisions as ADRs -- **Status:** Proposed +- **Status:** Accepted - **Date:** 2026-11-03 - **Deciders:** romchornyi (author). Team agreement: approval of #1308 by llbartekll. diff --git a/docs/adr/0002-keep-the-decision-log-in-docs-adr.md b/docs/adr/0002-keep-the-decision-log-in-docs-adr.md index f5275ed8d3..01635ce3f6 100644 --- a/docs/adr/0002-keep-the-decision-log-in-docs-adr.md +++ b/docs/adr/0002-keep-the-decision-log-in-docs-adr.md @@ -1,6 +1,6 @@ # 0002 — Keep the decision log in docs/adr -- **Status:** Proposed +- **Status:** Accepted - **Date:** 2026-11-03 - **Deciders:** romchornyi (author) diff --git a/docs/adr/README.md b/docs/adr/README.md index 73ea18d239..473092fd04 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -7,8 +7,8 @@ where they disagree, ADR-0001 wins. | # | Title | Area | Status | Superseded by | |---|---|---|---|---| -| [0001](0001-record-architecture-decisions-as-adrs.md) | Record architecture decisions as ADRs | process | Proposed | | -| [0002](0002-keep-the-decision-log-in-docs-adr.md) | Keep the decision log in docs/adr | process | Proposed | | +| [0001](0001-record-architecture-decisions-as-adrs.md) | Record architecture decisions as ADRs | process | Accepted | | +| [0002](0002-keep-the-decision-log-in-docs-adr.md) | Keep the decision log in docs/adr | process | Accepted | | Areas: `spv`, `platform`, `keys`, `storage`, `coinjoin`, `ui`, `build`, `process`. Each ADR takes one; a new Area is added to this list in the PR that first needs it.