From 880862bdf63672676a0fcfb4e6d0770a729ca801 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20Sodr=C3=A9?= Date: Thu, 11 Jun 2026 21:20:07 -0400 Subject: [PATCH 1/4] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor(adr):=20resol?= =?UTF-8?q?ve=20duplicate=20ADR-121=20by=20renumbering=20policy-rename=20t?= =?UTF-8?q?o=20124?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two Accepted ADRs both claimed number 121 on main: - 121-native-sync-unasync.md (created first, referenced by CLAUDE.md) - 121-policy-rename-clarity.md (created later, amends ADR-117) Native-sync keeps 121 since it is the earlier file and is referenced externally (CLAUDE.md). Renumber the IAM policy-rename ADR to 124 (next free number after 123-local-secondary-indexes). This is a structural collision fix, not a decision change, so it is consistent with the ADR immutability rule. Co-Authored-By: Claude Opus 4.8 (1M context) --- ...21-policy-rename-clarity.md => 124-policy-rename-clarity.md} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename docs/adr/{121-policy-rename-clarity.md => 124-policy-rename-clarity.md} (98%) diff --git a/docs/adr/121-policy-rename-clarity.md b/docs/adr/124-policy-rename-clarity.md similarity index 98% rename from docs/adr/121-policy-rename-clarity.md rename to docs/adr/124-policy-rename-clarity.md index 1f4f6482..1c8d077a 100644 --- a/docs/adr/121-policy-rename-clarity.md +++ b/docs/adr/124-policy-rename-clarity.md @@ -1,4 +1,4 @@ -# ADR-121: Rename IAM Policies for Clarity +# ADR-124: Rename IAM Policies for Clarity **Status:** Accepted **Date:** 2026-02-02 From 35ab3ff3eb52d5b0bfd7d3ad5830b21f749de86b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20Sodr=C3=A9?= Date: Thu, 11 Jun 2026 21:33:17 -0400 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=93=9D=20docs(adr):=20normalize=20ADR?= =?UTF-8?q?-121=20status=20header=20to=20ADR-000=20format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ADR-121 (native-sync) used a `## Status` heading with the value on a separate line, unlike every other ADR which uses the `**Status:**` / `**Date:**` inline format mandated by ADR-000. Normalize it (Date taken from the file's creation commit, 2026-02-02). Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/adr/121-native-sync-unasync.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/adr/121-native-sync-unasync.md b/docs/adr/121-native-sync-unasync.md index f2c891e2..e96ad4be 100644 --- a/docs/adr/121-native-sync-unasync.md +++ b/docs/adr/121-native-sync-unasync.md @@ -1,8 +1,7 @@ # ADR-121: Native Sync Implementation via Unasync Pattern -## Status - -Accepted +**Status:** Accepted +**Date:** 2026-02-02 ## Context From 4b33689d2d80cb182416f5c9a029d218849edf36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20Sodr=C3=A9?= Date: Thu, 11 Jun 2026 21:33:17 -0400 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=93=9D=20docs:=20add=20ADRs=20114-124?= =?UTF-8?q?=20to=20mkdocs=20navigation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ADR nav stopped at ADR-113; ADRs 114-124 existed as files but were unreachable from the docs site. Add thematic groups (Composite Items, IAM Resources, Config Hierarchy & TTL, Sync & Repository, Pre-1.0 Hardening) covering 114-124, reflecting the corrected numbering (121=native-sync, 124=policy-rename). Co-Authored-By: Claude Opus 4.8 (1M context) --- mkdocs.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/mkdocs.yml b/mkdocs.yml index bdc6e2e4..cd8a926e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -170,3 +170,19 @@ nav: - ADR-111 Flatten All Records: adr/111-flatten-all-records.md - ADR-112 Cascade Per Entity: adr/112-cascade-per-entity.md - ADR-113 Lambda Packaging: adr/113-lambda-packaging.md + - Composite Items (v0.8.0): + - ADR-114 Composite Bucket Items: adr/114-composite-bucket-items.md + - ADR-115 ADD-Based Writes: adr/115-add-based-writes-lazy-refill.md + - IAM Resources (v0.9.0): + - ADR-116 IAM Role Naming: adr/116-iam-role-naming.md + - ADR-117 Managed Policies by Default: adr/117-managed-policies-by-default.md + - ADR-124 Rename IAM Policies: adr/124-policy-rename-clarity.md + - Config Hierarchy & TTL (v0.8.0+): + - ADR-118 Four-Level Config Hierarchy: adr/118-four-level-config-hierarchy.md + - ADR-119 Bucket TTL Strategy: adr/119-bucket-ttl-strategy.md + - ADR-120 Bucket Param Sync: adr/120-bucket-param-sync.md + - Sync & Repository (v0.9.0+): + - ADR-121 Native Sync (Unasync): adr/121-native-sync-unasync.md + - ADR-122 Resolve Limits on Repository: adr/122-resolve-limits-on-repository.md + - Pre-1.0 Hardening (v0.10.0+): + - ADR-123 Local Secondary Indexes: adr/123-local-secondary-indexes.md From 30542875be9272c1428e0c0aeb4388e4af5d7dbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20Sodr=C3=A9?= Date: Thu, 11 Jun 2026 21:47:40 -0400 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=93=9D=20docs(adr):=20resolve=20cross?= =?UTF-8?q?-ADR=20consistency=20issues=20(107,=20100,=20013)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Surfaced by the /adr consistency audit: - ADR-107: annotate the partial supersession by ADR-117. Two Accepted ADRs asserted opposite IAM defaults (roles-by-default vs policies-by- default). Flag it in the status line and add a Decision note pointing to ADR-117 (current default) and ADR-124 (policy rename), so the reversed default is unambiguous to readers/enforcement. - ADR-100: this Proposed index still presented superseded sub-decisions (102→118, 103→122) as authoritative and used the pre-composite `#LIMIT#` schema. Add a standing note, mark the superseded rows, and show current composite `#CONFIG` keys alongside the originals. - ADR-013: accept it. It was Proposed yet already superseded ADR-012 — an invalid state. Its decision is complete and already operationalized as .claude/rules/docs-parity.md, so finalize the status. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/adr/013-module-documentation-parity.md | 2 +- docs/adr/100-centralized-config.md | 18 +++++++++++------- .../107-iam-roles-for-application-access.md | 4 +++- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/docs/adr/013-module-documentation-parity.md b/docs/adr/013-module-documentation-parity.md index 39e19860..f5df0686 100644 --- a/docs/adr/013-module-documentation-parity.md +++ b/docs/adr/013-module-documentation-parity.md @@ -1,6 +1,6 @@ # ADR-013: Bidirectional Source-Documentation Parity -**Status:** Proposed +**Status:** Accepted **Date:** 2026-01-19 **Supersedes:** ADR-012 diff --git a/docs/adr/100-centralized-config.md b/docs/adr/100-centralized-config.md index 63214a01..277f273e 100644 --- a/docs/adr/100-centralized-config.md +++ b/docs/adr/100-centralized-config.md @@ -5,6 +5,8 @@ **Issue:** [#129](https://github.com/zeroae/zae-limiter/issues/129) **Milestone:** v0.5.0 +> **Note (post-v0.5.0):** This is the original index for the centralized-config design. Two sub-decisions have since been superseded — the hierarchy expanded from three to four levels ([ADR-118](118-four-level-config-hierarchy.md) supersedes [ADR-102](102-config-hierarchy.md)) and limit resolution/caching moved to the Repository protocol ([ADR-122](122-resolve-limits-on-repository.md) supersedes [ADR-103](103-config-caching.md)). The original per-limit `#LIMIT#` config keys were replaced by composite `#CONFIG` items ([ADR-114](114-composite-bucket-items.md), [ADR-115](115-add-based-writes-lazy-refill.md)). See the updated access patterns below. + ## Context zae-limiter is a distributed rate limiting library where multiple clients must behave consistently. Currently: @@ -21,8 +23,8 @@ Implement centralized configuration with these architectural choices: | Decision | ADR | Summary | |----------|-----|---------| | Schema format | [ADR-101](101-flat-schema-config.md) | Flat schema (no nested `data.M`) for atomic counters | -| Config hierarchy | [ADR-102](102-config-hierarchy.md) | Three levels: System > Resource > Entity | -| Caching strategy | [ADR-103](103-config-caching.md) | 60s TTL with negative caching | +| Config hierarchy | [ADR-102](102-config-hierarchy.md) *(superseded by [ADR-118](118-four-level-config-hierarchy.md))* | Three levels: System > Resource > Entity — later expanded to four | +| Caching strategy | [ADR-103](103-config-caching.md) *(superseded by [ADR-122](122-resolve-limits-on-repository.md))* | 60s TTL with negative caching; resolution later moved to the Repository protocol | | API behavior | [ADR-104](104-stored-limits-default.md) | Stored limits as default | | Read consistency | [ADR-105](105-eventual-consistency.md) | Eventually consistent reads | @@ -41,11 +43,13 @@ Implement centralized configuration with these architectural choices: ## Access Patterns Added -| Pattern | Query | Index | -|---------|-------|-------| -| Get system config | `PK=SYSTEM#, SK begins_with #LIMIT#` | Primary | -| Get resource config | `PK=RESOURCE#{resource}, SK begins_with #LIMIT#` | Primary | -| Get entity config | `PK=ENTITY#{id}, SK begins_with #LIMIT#` | Primary | +> The original per-limit sort keys (`SK begins_with #LIMIT#`) were replaced by composite config items ([ADR-114](114-composite-bucket-items.md), [ADR-118](118-four-level-config-hierarchy.md)): a single `#CONFIG` item per level, namespace-prefixed with `{ns}/`. Both are shown below. + +| Pattern | Query (v0.5.0, original) | Current | +|---------|--------------------------|---------| +| Get system config | `PK=SYSTEM#, SK begins_with #LIMIT#` | `PK={ns}/SYSTEM#, SK=#CONFIG` | +| Get resource config | `PK=RESOURCE#{resource}, SK begins_with #LIMIT#` | `PK={ns}/RESOURCE#{resource}, SK=#CONFIG` | +| Get entity config | `PK=ENTITY#{id}, SK begins_with #LIMIT#` | `PK={ns}/ENTITY#{id}, SK=#CONFIG#{resource}` | ## Implementation diff --git a/docs/adr/107-iam-roles-for-application-access.md b/docs/adr/107-iam-roles-for-application-access.md index 5f8f2e40..8fb7ab09 100644 --- a/docs/adr/107-iam-roles-for-application-access.md +++ b/docs/adr/107-iam-roles-for-application-access.md @@ -1,6 +1,6 @@ # ADR-107: IAM Roles for Application Access -**Status:** Accepted +**Status:** Accepted (IAM defaults partially superseded by [ADR-117](117-managed-policies-by-default.md)) **Date:** 2026-01-19 **Issue:** [#132](https://github.com/zeroae/zae-limiter/issues/132) @@ -14,6 +14,8 @@ The CloudFormation stack currently only creates the Lambda execution role for th The CloudFormation stack creates three optional IAM roles (AppRole, AdminRole, ReadOnlyRole) with least-privilege DynamoDB permissions, enabled by default and controlled via `--no-iam-roles` flag or `StackOptions.create_iam_roles=False`. +> **Partially superseded by [ADR-117](117-managed-policies-by-default.md):** managed *policies* are now created by default and IAM *roles* are opt-in (`create_iam_roles=True` / `--create-iam-roles`). The "enabled by default / `--no-iam-roles`" default above no longer reflects current behavior. The three-tier app/admin/read-only access model is retained; [ADR-124](124-policy-rename-clarity.md) later renamed the policies to AcquireOnly/FullAccess/ReadOnly. + ## Consequences **Positive:**