Skip to content

Commit 5a88a99

Browse files
authored
chore(release): prepare 0.2.5 (#35)
* docs: open v1.15 milestone — AUD-14 planning truth + phase 78 * chore: archive v1.15 milestone files Made-with: Cursor * chore: remove REQUIREMENTS.md for v1.15 milestone Made-with: Cursor * feat(audit): v1.16 transactional api.token_verify.failure (phase 79 AUD-16) * chore: archive v1.16 milestone files Made-with: Cursor * chore: remove REQUIREMENTS.md for v1.16 milestone Made-with: Cursor * docs: start milestone v1.17 forced-change audit atomicity * docs: define milestone v1.17 requirements * docs: create milestone v1.17 roadmap (1 phase) * docs(80): capture phase context and audit defaults * docs(state): record phase 80 context session * docs(phase-80): research, validation strategy, and executable plans * feat(80-01): add clear_password_change_requirement/3 and deprecate audit_forced_password_change Made-with: Cursor * test(80-01): add Postgres atomicity tests for clear_password_change_requirement Made-with: Cursor * docs(phase-80): complete v1.17 AUD-17 — inventory, C-1, CHANGELOG, milestone archives - Ship planning truth for AUD-04-043 / EX-44-05 (44 inventory, 09 verification, 09-03-SUMMARY) - Add 80-01/80-02 SUMMARY, 80-REVIEW, 80-VERIFICATION; archive v1.17 ROADMAP/REQUIREMENTS - Fix STATE/ROADMAP/PROJECT after phase completion; REQUIREMENTS marked complete Made-with: Cursor * chore: archive v1.17 milestone Remove live REQUIREMENTS.md for a clean next milestone; add MILESTONES and RETROSPECTIVE entries; point ROADMAP at archived requirements; sync STATE and PROJECT footers. Made-with: Cursor * docs: start milestone v1.18 JWT refresh audit atomicity * docs: define milestone v1.18 requirements * docs: create milestone v1.18 roadmap (1 phase) * docs(81): capture phase context + audit defaults shift-left * docs(state): record phase 81 context session * docs(81): research, validation strategy, and executable plans for JWT audit atomicity Made-with: Cursor * feat(81-01): transactional Multi audit for JWT refresh and reuse Implement commit_api_token_jwt_audit/3 mirroring verify-failure audit path: Repo.transaction + Audit.log_multi_safe, telemetry from changes, invalid changeset and constraint_violation handling. Replace log_safe in audit_jwt_*. Refs: AUD-18-01, AUD-18-02 Made-with: Cursor * docs(81-01): plan summary for JWT Multi audit Made-with: Cursor * test(81-02): ExUnit coverage for JWT refresh Multi audit paths Happy path, audit-off, CHECK fault injection with log_safe_error telemetry for api.jwt_refresh and api.jwt_refresh_reuse. Refs: AUD-18-03 Made-with: Cursor * docs(81-03): AUD-18 planning truth and phase 81 verification Align AUD-04-048/049 across 44/45 inventories and 09 C-1; CHANGELOG [Unreleased]; 81-VERIFICATION merge gate; 09-03-SUMMARY bounded-batch note. Refs: AUD-18-04 Made-with: Cursor * docs(81-02): plan summary for JWT audit ExUnit coverage Made-with: Cursor * docs(81-03): plan summary for AUD-18 planning alignment Made-with: Cursor * docs(phase-81): complete milestone tracking and verification status Mark AUD-18 requirements done; archive v1.18 in ROADMAP; fix STATE after phase.complete; add 81-REVIEW quick pass; 81-VERIFICATION status passed. Refs: AUD-18 Made-with: Cursor * docs(09-03): document status line for phase 81 AUD-18 Made-with: Cursor * docs(phase-81): add/update security threat verification * docs(phase-81): add/update validation strategy * docs: start milestone v1.19 JWT persistence audit co-fate + MFA 022 * docs(82): capture JWT refresh persistence audit co-fate context * docs(state): record phase 82 context session * docs(state): fix resume path after phase 82 discuss * docs(phase-82): research, validation strategy, and executable plans (AUD-19) * docs(phase-82): drop spurious PLANNING COMPLETE markers from plans * feat(phase-82): JWT refresh persistence + audit co-fate (AUD-19) - Compose user_tokens rotation/reuse and api.jwt_refresh* in one Repo.transaction when :audit_schema is set (Sigra.JWT.refresh/3, Sigra.Auth.refresh_jwt/2). - Add APIToken.append_api_token_jwt_audit_to_multi/3 and jwt_refresh_audit_multi_opts. - RefreshToken: Multi builders, classify_refresh_token, rotate_with_reuse_meta; emit refresh_reuse_detected from JWT only. - Add test/sigra/jwt_refresh_audit_cofate_test.exs (async: false). - Planning: 44/45/09 inventories, 09-03-SUMMARY, CHANGELOG, 82-VERIFICATION (pending until Postgres mix test run), REQUIREMENTS AUD-19 checkboxes, ROADMAP/STATE. Made-with: Cursor * docs(83): phase context, discuss log, D-AUD-12, GSD discuss prefs * docs(state): record phase 83 discuss session * docs(83): research, validation strategy, and executable plans for AUD-04-022 * feat(83-01): route confirm_enrollment invalid TOTP audit through commit_ad_hoc_mfa_audit AUD-20-01: use Repo.transaction + Multi + log_multi_safe when :audit_schema is set; skip audit-only work when absent. Document return contract (D-83-02). Made-with: Cursor * test(83-02): cover confirm_enrollment invalid TOTP audit matrix AUD-20-02: audit on writes mfa.enroll.failure with metadata; audit off skips; CHECK guard emits log_safe_error without changing {:error, :invalid_code}. Made-with: Cursor * docs(83-03): AUD-20 planning truth for confirm_enrollment 022 Update 44 inventory + EX-44-02, 09 C-1 and summary, CHANGELOG [Unreleased]; add 83-VERIFICATION merge gate and 83-REVIEW quick pass. Made-with: Cursor * docs(phase-83): complete phase execution — ROADMAP, STATE, REQUIREMENTS, PROJECT Mark v1.19 Phases 82–83 shipped; advance focus to 999.1; check off AUD-20. Made-with: Cursor * docs(84-01): reconcile live routing surfaces - point active planning state at Phase 84 instead of 999.1 - mark 999.x as archaeology-only and reserve future work for newly numbered phases * docs(84-01): add routing cleanup verification artifact - record requirement-level evidence for live routing cleanup - capture exact grep and file-existence checks for the 999.1 tombstone chain * docs(84-01): complete routing honesty reconciliation plan - record phase 84 summary and self-check results - mark planning state and roadmap surfaces complete for the routing cleanup * docs(phase-84): verify and finalize routing honesty reconciliation * chore(release): prepare 0.2.5
1 parent 3bf48a6 commit 5a88a99

83 files changed

Lines changed: 6045 additions & 241 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Sigra — audit atomicity defaults (GSD / planning)
2+
3+
**Purpose:** Capture **default engineering choices** for bounded **SEED-002**–style phases and `/gsd-discuss-phase` so planners rarely re-open settled tradeoffs. **Override** in phase CONTEXT when a requirement truly demands an exception (call that out explicitly).
4+
5+
**Status:** Established **2026-04-24** (Phase 80 research synthesis); extended **D-AUD-05..07** **2026-04-24** (Phase 81 JWT audit-only slice + discuss shift-left); **D-AUD-12** + discuss delegation prefs **2026-04-24** (Phase **83**).
6+
7+
## Defaults
8+
9+
### D-AUD-01 — Orchestration layer
10+
11+
- **`Sigra.Account`** (and analogous top-level orchestrators) **own** `Repo.transaction/1`, `Ecto.Multi`, and `Sigra.Audit.log_multi_safe/3` when audit must share fate with domain writes.
12+
- **Domain modules** (`Sigra.Account.PasswordChange`, `EmailChange`, `Deletion`, …) stay **audit-agnostic**: no `Sigra.Audit` imports; they expose changesets, `Repo` operations, or small `Multi.run`-friendly steps.
13+
- **Rationale:** Matches Phoenix **context** orchestration, avoids ActiveRecord/Django-signal-style hidden coupling, keeps **one transaction owner**, reduces nested-transaction footguns, improves generator DX (single extension seam).
14+
15+
### D-AUD-02 — Deprecation of superseded audit-only helpers
16+
17+
- When a standalone `log_safe/3` helper is replaced by an atomic **`Multi` + `log_multi_safe`** path: **`@deprecated`** with a **compile-time** warning for **at least one minor**, then **remove** in the following minor (pre-1.0). Document the **single supported** call sequence in CHANGELOG + upgrade guide.
18+
- **Avoid:** immediate patch removal of public APIs; long-lived “smart no-op” shims without idempotency keys; default **runtime raise** for “double audit” in production (prefer CI / docs / generator alignment).
19+
20+
### D-AUD-03 — Options keyword shape
21+
22+
- Public **`Sigra.Account.*`** arities keep **`(repo, …, opts)`** with the **same physical `opts` keyword** hosts/generators already pass for `change_password`, email flows, etc.
23+
- Implementations **`Keyword.take`** / NimbleOptions **composed schemas** so each operation uses the **audit context slice** consistently; operation-specific keys are validated per function without inventing a second public opts bag.
24+
25+
### D-AUD-04 — Testing split
26+
27+
- **MockRepo / unit:** API contracts, branches, error tuples, composition (no second Postgres copy of every branch).
28+
- **Postgres + fault injection (`CHECK` / similar):** **one** happy path + **one** rollback proof per atomic story in `*_audit_atomicity_test.exs` (or equivalent), mirroring existing `change_password` patterns.
29+
30+
### D-AUD-05 — Audit-only `Multi` (no domain step)
31+
32+
- Helpers that **only** persist an audit row (e.g. **`api.jwt_refresh`**, **`api.jwt_refresh_reuse`**) still use **`Repo.transaction/1` + `Ecto.Multi` + `Sigra.Audit.log_multi_safe/3`** when `:audit_schema` is set — same **durability class** as token verify failure audits — with a **single private `commit_*`** owning the transaction shell and **thin `def` wrappers** for action-specific opts.
33+
- **Do not** imply **shared fate** with unrelated domain tables unless a future phase explicitly joins them in the same `Multi` (**AUD-08**-class work stays out of bounded SEED-002 slices unless scoped).
34+
35+
### D-AUD-06 — Caller contract when audit insert fails (audit-only paths)
36+
37+
- Public functions that today return **`:ok`** and use **`log_safe`/`log_multi_safe`** for **side-channel audit** keep **`:ok`** on audit subsystem failure; emit **`[:sigra, :audit, :log_safe_error]`** (or the same telemetry contract as `emit_log_safe_error`) so operators can alert; **raise** only on programmer-wiring errors. **`@doc`** must state **`:ok` does not guarantee** the audit row exists.
38+
39+
### D-AUD-07 — ExUnit layout for audit fault injection
40+
41+
- **Separate named tests** per action × fault story (no parametrized loops for fault paths). Reuse **only** small private helpers for `ALTER … CHECK` + `try/after` + telemetry attach; **unique** handler IDs per test; **`async: false`**; action-scoped SQL counts.
42+
43+
### D-AUD-08 — Persistence + audit co-fate (JWT refresh class; **AUD-19**)
44+
45+
- When requirements mandate **one commit** for **domain `user_tokens` effects** and **`api.jwt_refresh*`** audit rows (**:audit_schema** set):
46+
- **Orchestrator** (**`Sigra.JWT.refresh/3`**, optionally delegated to an internal **`@moduledoc false`** module) owns **exactly one** **`Repo.transaction/1`** (or **`Repo.transact/2`** if the project adopts it here).
47+
- **`Sigra.APIToken`** (or equivalent) must expose audit as **`Ecto.Multi` steps** composable into that transaction — **do not** call **`Repo.transaction`** inside helpers used from that **`Multi`** (no nested txn / savepoint surprise).
48+
- **Public contract:** **`{:ok, tokens}`** iff the **full bundle** commits; **any** step failure → rollback and **`{:error, _}`****explicit exception** to **D-AUD-06** for this class only. **`@doc`** must contrast with **`audit_jwt_refresh/2`** / **`audit_jwt_refresh_reuse/2`** standalone semantics (**`:ok`** + telemetry on audit-only failure).
49+
- **Rationale:** **D-AUD-06** exists because audit-only paths cannot roll back already-committed host work; co-fate paths **can** and **must** roll back persistence when audit fails — returning **`:ok`** with tokens would violate least surprise and audit integrity.
50+
51+
### D-AUD-09 — Security telemetry after commit (reuse / co-fate)
52+
53+
- **`Telemetry.event/3`** (or similar) that implies **persisted** security outcomes (**reuse detected**, family revoked) must run **after** the transaction **commits** (success branch), not interleaved between persistence and audit where a later audit failure would roll back DB state but leave misleading signals.
54+
55+
### D-AUD-10 — ExUnit split: audit-only vs persistence co-fate
56+
57+
- **Audit-only** stories (helpers that do not join **`user_tokens`** writes in the same txn) stay in **`api_token_audit_atomic_test.exs`** (or the established audit-atomicity module for that surface).
58+
- **Persistence + audit co-fate** proofs live in a **dedicated** file (e.g. **`jwt_refresh_audit_cofate_test.exs`**) with **`@moduledoc`** cross-linking the audit-only module — preserves CI failure labels and avoids conflating **D-AUD-06** contracts with **D-AUD-08** contracts in one module.
59+
60+
### D-AUD-11 — Planning matrix updates when **T1** semantics strengthen
61+
62+
- Prefer **surgical cell edits** + **one dated supersession footnote** (phase id + what narrowed, e.g. **AUD-08** closed) across **44** / **45** / **09-VERIFICATION** / **09-03-SUMMARY** in lockstep; **`CHANGELOG` [Unreleased]** carries the user-visible behavior story; phase **`NN-VERIFICATION.md`** is the merge gate spine. Avoid wholesale matrix rewrites unless the row taxonomy is wrong.
63+
64+
### D-AUD-12 — MFA invalid pre-DB enrollment attempt (**AUD-04-022**)
65+
66+
- When **`:audit_schema`** is set, **`Sigra.MFA.confirm_enrollment/5`** wrong-TOTP path (**before** enrollment `Multi`) persists **`mfa.enroll.failure`** via **`Repo.transaction/1` + `Ecto.Multi` + `Sigra.Audit.log_multi_safe/3`**, using the **same audit-only shell** as **`commit_ad_hoc_mfa_audit/5`** (success → **`emit_telemetry_from_changes`**; failure → **`[:sigra, :audit, :log_safe_error]`** per existing rescue/changeset paths).
67+
- **Public return:** **`{:error, :invalid_code}`** whenever the TOTP check fails — **independent** of audit insert outcome (**not** **D-AUD-08**; not a new failure atom for audit DB issues).
68+
- **Explicit waiver** (retain **`log_safe`**) remains valid only if a phase **CONTEXT** records an intentional **exception to D-AUD-05** with updated **EX-44-02** rationale (**AUD-20-01** second branch).
69+
70+
## Discuss-phase preferences (this project)
71+
72+
- When the user **delegates** (“all”, “synthesize”, “don’t make me think”), default orchestrator behavior: **parallel research** (subagents or equivalent) on listed gray areas → **one coherent CONTEXT** aligned with **PROJECT.md** / **REQUIREMENTS.md** / these defaults.
73+
- **Still require explicit user choices** for topics in **`.planning/config.json``workflow.discuss_always_surface_for_user`** (semver/public API, security model vs published OWASP stance, generator/host output contracts).
74+
75+
## When to still run discuss-phase
76+
77+
Use `/gsd-discuss-phase` when any of: new **external** contract (HTTP, host generator output), **semver exception**, **cross-cutting** audit API change (e.g. new `log_multi_safe` step names), **persistence + audit co-fate** scope not already covered by **D-AUD-08**, or **explicit** stakeholder preference. Otherwise planners may treat **D-AUD-01..11** as locked unless phase SPEC says otherwise.

.planning/MILESTONES.md

Lines changed: 101 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@
4545
- `SEED-001` — 8 human-only UAT items to run before GA public announcement (email visual × 4, OAuth real-credential × 4)
4646
- `SEED-002` — Phase 9 `log_safe/3` hybrid to atomic `Ecto.Multi` conversion (C-1 caveat followup)
4747

48-
**Backlog** (999.x parking lot):
49-
- `Phase 999.1` — Retroactive Nyquist validation pass for 6 draft + 1 missing VALIDATION.md files
50-
- `Phase 999.2` — Dependabot major-version bumps (setup-node 4→6, upload-artifact 4→7, checkout 4→6) requiring per-bump CI verification
48+
**Backlog** (999.x parking lot; archaeology only):
49+
- `Phase 999.1` — Retroactive Nyquist validation pass for 6 draft + 1 missing VALIDATION.md files; shipped in v1.3 and now retained as a tombstone/pointer only
50+
- `Phase 999.2` — Dependabot major-version bumps (setup-node 4→6, upload-artifact 4→7, checkout 4→6) requiring per-bump CI verification; historical parking-lot label only until promoted into a newly numbered phase
5151

5252
**Archive:**
5353
- [v1.0 Roadmap](milestones/v1.0-ROADMAP.md) — full phase details
@@ -81,7 +81,7 @@
8181
### Tech Debt Carried Forward
8282

8383
- **`gsd-tools audit-open --json` is deprecated** for Sigra maintainers; the **supported path** is [`MAINTAINING.md`](../MAINTAINING.md) section **Planning hygiene (without gsd-tools JSON)** plus optional [`scripts/maintainers/planning-audit-hygiene.sh`](../scripts/maintainers/planning-audit-hygiene.sh).
84-
- `Phase 999.1` Nyquist backfill remains parked.
84+
- `Phase 999.1` Nyquist backfill remains archaeology-only; Phase 84 owns the routing-honesty cleanup so active workflows stop pointing at the tombstone.
8585
- `Phase 999.2` Dependabot major-version cleanup remains parked.
8686

8787
**Archive:**
@@ -114,7 +114,7 @@
114114

115115
### Tech Debt Carried Forward
116116

117-
- `SEED-001` human-only GA UAT items; `SEED-002` audit atomicity hybrid; backlog **999.1** / **999.2** unchanged from prior milestones.
117+
- `SEED-001` human-only GA UAT items; `SEED-002` audit atomicity hybrid; backlog **999.1** / **999.2** remain historical parking-lot labels only.
118118
- Residual subjective reviewer items called out in phase VERIFICATION/HUMAN-UAT docs where automation cannot fully substitute judgment.
119119

120120
**Archive:**
@@ -489,3 +489,99 @@
489489
- [v1.14 Requirements](milestones/v1.14-REQUIREMENTS.md)
490490

491491
---
492+
493+
## v1.17 Forced password change audit atomicity (Shipped: 2026-04-24)
494+
495+
**Scope:** 1 phase (**80**), **`Sigra.Account.clear_password_change_requirement/3`** + planning truth (**AUD-17-01**..**AUD-17-04**).
496+
497+
**What shipped:** **`clear_password_change_requirement/3`** co-fates **`must_change_password: false`** with **`account.password_change`** (`metadata: %{forced: true}`) via **`Repo.transaction/1`** + **`Ecto.Multi`** + **`Sigra.Audit.log_multi_safe/3`** when `:audit_schema` is set; **`audit_forced_password_change/2`** **`@deprecated`**; **`test/sigra/account_audit_atomicity_test.exs`** forced-clear + CHECK rollback; **44** inventory + **09-VERIFICATION** C-1 **043** **T1** + **09-03-SUMMARY** + **`CHANGELOG` [Unreleased]**; **EX-44-05** closed.
498+
499+
### Key accomplishments
500+
501+
1. **AUD-17-01** — Forced-clear path matches atomic audit pattern used elsewhere on **Account**.
502+
2. **AUD-17-02** — Standalone post-commit **`log_safe`** for that completion path retired (**deprecation**).
503+
3. **AUD-17-03 / AUD-17-04** — Postgres-backed atomicity tests + planning truth aligned to **AUD-04-043**.
504+
505+
### Stats
506+
507+
- **Requirements:** 4/4 **Validated** in archived [`milestones/v1.17-REQUIREMENTS.md`](milestones/v1.17-REQUIREMENTS.md).
508+
- **Timeline:** **2026-04-24**; **`/gsd-complete-milestone`** — live **`REQUIREMENTS.md`** removed.
509+
- **Milestone audit:** not filed (optional); pre-close **`audit-open`**: all artifact types clear (2026-04-24).
510+
- **`gsd-sdk query milestone.complete`:** failed (`version required for phases archive`); manual **`milestones/v1.17-*`** archival (same pattern as **v1.12****v1.16**).
511+
- **Git (since `v1.16` tag):** 9 commits; **24** files (**1288** insertions / **50** deletions in `git diff --shortstat v1.16..HEAD` at close).
512+
513+
### Tech debt carried forward
514+
515+
- **SEED-002** — remaining **`log_safe/3`** clusters (**048–049**, OAuth phase **45**, etc.).
516+
- **AUD-04-022****`log_safe`** invalid enrollment path unchanged (**EX-44-02**).
517+
518+
**Archive:**
519+
520+
- [v1.17 Roadmap](milestones/v1.17-ROADMAP.md)
521+
- [v1.17 Requirements](milestones/v1.17-REQUIREMENTS.md)
522+
523+
---
524+
525+
## v1.16 API verify failure audit atomicity (Shipped: 2026-04-24)
526+
527+
**Scope:** 1 phase (**79**), **`Sigra.APIToken.verify/2`** failure audits + planning truth (**AUD-16-01**..**AUD-16-04**).
528+
529+
**What shipped:** **`api.token_verify.failure`** for invalid / revoked / expired branches uses **`Repo.transaction/1`** + **`Ecto.Multi`** + **`Sigra.Audit.log_multi_safe/3`** when `:audit_schema` is set; **`log_safe_error`** telemetry on audit insert failure while callers still receive **`{:error, reason}`**; **44** + **09** + **09-03-SUMMARY** + **`CHANGELOG` [Unreleased]**; **`test/sigra/api_token_audit_atomic_test.exs`** coverage + fault injection; **EX-44-01** verify slice retired (appendix row retained).
530+
531+
### Key accomplishments
532+
533+
1. **AUD-16-01 / AUD-16-02****`verify/2`** failure branches match atomic audit pattern without **D-27** success-path noise.
534+
2. **AUD-16-03****AUD-04-044..046** **T1** in **44** inventory + **09-VERIFICATION** C-1 matrix.
535+
3. **AUD-16-04** — Success path remains telemetry-only.
536+
537+
### Stats
538+
539+
- **Requirements:** 4/4 **Validated** in archived [`milestones/v1.16-REQUIREMENTS.md`](milestones/v1.16-REQUIREMENTS.md).
540+
- **Timeline:** **2026-04-24**; **`/gsd-complete-milestone`** same day — live **`REQUIREMENTS.md`** removed.
541+
- **Milestone audit:** not filed (optional); pre-close **`audit-open`**: all artifact types clear (2026-04-24).
542+
- **`gsd-sdk query milestone.complete`:** not relied on; manual **`milestones/v1.16-*`** archival (same pattern as **v1.12****v1.15**).
543+
- **Git (since `v1.15` tag):** 1 commit; **13** files (**487** insertions / **80** deletions in `git diff --shortstat 'v1.15^{}'..HEAD` at close).
544+
545+
### Tech debt carried forward
546+
547+
- **SEED-002** — remaining **`log_safe/3`** clusters (e.g. **043**, **048–049**, OAuth phase **45**).
548+
- **AUD-04-022****`log_safe`** invalid enrollment path unchanged (**EX-44-02**).
549+
550+
**Archive:**
551+
552+
- [v1.16 Roadmap](milestones/v1.16-ROADMAP.md)
553+
- [v1.16 Requirements](milestones/v1.16-REQUIREMENTS.md)
554+
555+
---
556+
557+
## v1.15 Account + API C-1 planning truth (Shipped: 2026-04-24)
558+
559+
**Scope:** 1 phase (**78**), library tests + planning truth (**AUD-14**..**AUD-14-05**).
560+
561+
**What shipped:** **`44-AUD-04-INVENTORY.md`** rows **035–042** and **047** aligned to **`Multi` + `log_multi_safe`** in **`lib/sigra/account.ex`** and **`lib/sigra/api_token.ex`**; **`09-VERIFICATION.md`** C-1 **T1**/**T2** honesty for those rows; **`09-03-SUMMARY.md`** bounded-batch note for **phase 78** / **AUD-14**; **`CHANGELOG.md` [Unreleased]** trace bullet; **`test/sigra/account_audit_atomicity_test.exs`** **`change_password`** success + CHECK-guard rollback.
562+
563+
### Key accomplishments
564+
565+
1. **AUD-14-01 / AUD-14-02** — Inventory rows match code for **Account** paths and **`APIToken.revoke/2`**, preserving **EX-44-05** and **EX-44-01** for **044–046** at **v1.15** close (**044–046** advanced in **v1.16** / **phase 79**).
566+
2. **AUD-14-03****09-VERIFICATION** Phase **44** table carries defensible **T1**/**T2** labels for **035–042**, **043**, **044–046**, **047**, **048–049**.
567+
3. **AUD-14-04 / AUD-14-05** — Summary + changelog trace; Postgres-backed atomicity tests for **`change_password`**.
568+
569+
### Stats
570+
571+
- **Requirements:** 5/5 **Validated** in archived [`milestones/v1.15-REQUIREMENTS.md`](milestones/v1.15-REQUIREMENTS.md).
572+
- **Timeline:** **2026-04-24**; **`/gsd-complete-milestone`** same day — live **`REQUIREMENTS.md`** removed.
573+
- **Milestone audit:** not filed (optional); pre-close **`audit-open`**: all artifact types clear (2026-04-24).
574+
- **`gsd-sdk query milestone.complete`:** failed (`version required for phases archive`); archival manual (same pattern as **v1.12****v1.14**).
575+
- **Git (since `v1.14` tag):** ~4 commits; **13** files (**282** insertions / **72** deletions in `git diff --shortstat v1.14..HEAD` at close).
576+
577+
### Tech debt carried forward
578+
579+
- **SEED-002** — remaining **`log_safe/3`** clusters per **44** / phase **45** inventory; backlog-triggered.
580+
- **AUD-04-022****`log_safe`** invalid enrollment path unchanged (**EX-44-02**).
581+
582+
**Archive:**
583+
584+
- [v1.15 Roadmap](milestones/v1.15-ROADMAP.md)
585+
- [v1.15 Requirements](milestones/v1.15-REQUIREMENTS.md)
586+
587+
---

0 commit comments

Comments
 (0)